From 559fd817ef7d4d5a4c773a9dae1c6ae13f3448e7 Mon Sep 17 00:00:00 2001 From: Godzil Date: Mon, 4 Feb 2013 17:09:58 +0100 Subject: [PATCH] Add UI definition, and preliminary support on major check loops. --- Makefile | 4 +-- src/check.c | 8 +++-- src/dosfsck.c | 46 +++++++++++++++++++----- src/fat.c | 2 ++ src/ui.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ui.h | 28 +++++++++++++++ 6 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 src/ui.c create mode 100644 src/ui.h diff --git a/Makefile b/Makefile index 4efa2d3..2e4416c 100644 --- a/Makefile +++ b/Makefile @@ -38,9 +38,9 @@ all: build build: dosfsck dosfslabel mkdosfs -dosfsck: boot.o check.o common.o fat.o file.o io.o lfn.o dosfsck.o +dosfsck: boot.o check.o common.o fat.o file.o io.o lfn.o dosfsck.o ui.o -dosfslabel: boot.o check.o common.o fat.o file.o io.o lfn.o dosfslabel.o +dosfslabel: boot.o check.o common.o fat.o file.o io.o lfn.o dosfslabel.o ui.o mkdosfs: mkdosfs.o diff --git a/src/check.c b/src/check.c index 1f427ed..730a596 100644 --- a/src/check.c +++ b/src/check.c @@ -37,6 +37,7 @@ #include "file.h" #include "lfn.h" #include "check.h" +#include "ui.h" static DOS_FILE *root; @@ -657,7 +658,7 @@ static int check_dir(DOS_FS * fs, DOS_FILE ** root, int dots) { DOS_FILE *parent, **walk, **scan; int dot, dotdot, skip, redo; - int good, bad; + int good, bad, done = 0; if (!*root) return 0; @@ -685,6 +686,7 @@ static int check_dir(DOS_FS * fs, DOS_FILE ** root, int dots) dot = dotdot = redo = 0; walk = root; while (*walk) { + ui_print_progress(done++, bad + good); if (!strncmp ((const char *)((*walk)->dir_ent.name), MSDOS_DOT, MSDOS_NAME) || !strncmp((const char *)((*walk)->dir_ent.name), MSDOS_DOTDOT, @@ -1040,9 +1042,11 @@ int scan_root(DOS_FS * fs) if (fs->root_cluster) { add_file(fs, &chain, NULL, 0, &fp_root); } else { - for (i = 0; i < fs->root_entries; i++) + for (i = 0; i < fs->root_entries; i++) { + ui_print_progress(i, fs->root_entries); add_file(fs, &chain, NULL, fs->root_start + i * sizeof(DIR_ENT), &fp_root); + } } lfn_check_orphaned(); (void)check_dir(fs, &root, 0); diff --git a/src/dosfsck.c b/src/dosfsck.c index 2750953..8241f27 100644 --- a/src/dosfsck.c +++ b/src/dosfsck.c @@ -3,6 +3,7 @@ Copyright (C) 1993 Werner Almesberger Copyright (C) 1998 Roman Hodek Copyright (C) 2008-2013 Daniel Baumann + Copyright (C) 2013 Manoel Trapier This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,8 +41,10 @@ #include "fat.h" #include "file.h" #include "check.h" +#include "ui.h" int interactive = 0, rw = 0, list = 0, test = 0, verbose = 0, write_immed = 0; +extern int output_ui_fd, output_ui; int atari_format = 0, boot_only = 0; unsigned n_files = 0; void *mem_queue = NULL; @@ -56,6 +59,7 @@ static void usage(char *name) fprintf(stderr, " -d path drop that file\n"); fprintf(stderr, " -f salvage unused chains to files\n"); fprintf(stderr, " -l list path names\n"); + fprintf(stderr, " -C [fd] Display completion to fd file descriptor\n"); fprintf(stderr, " -n no-op, check non-interactively without changing\n"); fprintf(stderr, " -p same as -a, for compat with other *fsck\n"); @@ -109,9 +113,9 @@ int main(int argc, char **argv) interactive = 1; check_atari(); - while ((c = getopt(argc, argv, "Aad:bflnprtu:vVwy")) != EOF) + while ((c = getopt(argc, argv, "Aad:bC:flnprtu:vVwy")) != EOF) switch (c) { - case 'A': /* toggle Atari format */ + case 'A': /* toggle Atari format */ atari_format = !atari_format; break; case 'a': @@ -159,6 +163,10 @@ int main(int argc, char **argv) case 'w': write_immed = 1; break; + case 'C': + output_ui_fd = atoi(optarg); + output_ui = 1; + break; default: usage(argv[0]); } @@ -169,30 +177,48 @@ int main(int argc, char **argv) if (optind != argc - 1) usage(argv[0]); - printf("dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n"); - fs_open(argv[optind], rw); + printf("dosfsck " VERSION ", " VERSION_DATE ", FAT32, LFN\n"); + /* Now open FileSystem, and do all the checks.. */ + fs_open(argv[optind], rw); + ui_set_device(argv[optind]); + + ui_print_new_pass("Checking boot sector..."); read_boot(&fs); if (boot_only) - goto exit; + goto exit; if (verify) printf("Starting check/repair pass.\n"); + + ui_print_new_pass("Scanning FAT..."); while (read_fat(&fs), scan_root(&fs)) qfree(&mem_queue); - if (test) + + if (test) { + ui_print_new_pass("Fix bad FAT..."); fix_bad(&fs); - if (salvage_files) + } + + if (salvage_files) { + ui_print_new_pass("Reclaim bad file..."); reclaim_file(&fs); - else + } + else { + ui_print_new_pass("Reclaim free space..."); reclaim_free(&fs); + } + + ui_print_new_pass("Verify free clusters..."); free_clusters = update_free(&fs); file_unused(); qfree(&mem_queue); n_files_check = n_files; + if (verify) { n_files = 0; printf("Starting verification pass.\n"); + ui_print_new_pass("Starting verification pass..."); read_fat(&fs); scan_root(&fs); reclaim_free(&fs); @@ -205,8 +231,10 @@ exit: if (rw) { if (interactive) rw = get_key("yn", "Perform changes ? (y/n)") == 'y'; - else + else { + ui_print_new_pass("Performing changes..."); printf("Performing changes.\n"); + } } else printf("Leaving file system unchanged.\n"); } diff --git a/src/fat.c b/src/fat.c index 45575cb..655e651 100644 --- a/src/fat.c +++ b/src/fat.c @@ -34,6 +34,7 @@ #include "io.h" #include "check.h" #include "fat.h" +#include "ui.h" /** * Fetch the FAT entry for a specified cluster. @@ -148,6 +149,7 @@ void read_fat(DOS_FS * fs) /* Truncate any cluster chains that link to something out of range */ for (i = 2; i < fs->clusters + 2; i++) { + ui_print_progress(i - 2, fs->clusters - 2); FAT_ENTRY curEntry; get_fat(&curEntry, fs->fat, i, fs); if (curEntry.value == 1) { diff --git a/src/ui.c b/src/ui.c new file mode 100644 index 0000000..e7931f7 --- /dev/null +++ b/src/ui.c @@ -0,0 +1,98 @@ +/* ui.c - Functions for handling the UI interface + + Copyright (C) 2013 Manoel Trapier + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + On Debian systems, the complete text of the GNU General Public License + can be found in /usr/share/common-licenses/GPL-3 file. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BAR (50) + +int output_ui_fd, output_ui; +static uint16_t current_pass = 0; +static const char rotator[] = "|/-\\"; + +static char *cur_device; + +static void ui_print_text(char *text) +{ + if (output_ui == 1) { + if (output_ui_fd < 0) { + write(-output_ui_fd, text, strlen(text)); + fsync(-output_ui_fd); + } + else if (output_ui_fd == 0) { + write(1, text, strlen(text)); + fsync(1); + } + else { + write(output_ui_fd, text, strlen(text)); + fsync(output_ui_fd); + } + } +} + +void ui_print_new_pass(char *text) +{ + if (output_ui == 1) + { + char buffer[256]; + current_pass++; + sprintf(buffer, "Pass %d: %s\n", current_pass, text); + ui_print_text(buffer); + } +} + +void ui_print_progress(int pos, int max) +{ + if (output_ui == 1) + { + char buffer[256]; + static uint8_t last_car = 0; + + if (output_ui_fd == 0) { + float percent = (pos / max) * 100; + char bar[60]; + int nbbar = (pos * MAX_BAR) / 100; + int i; + memset(bar, 0, 60); + for(i = 0 ; i < MAX_BAR ; i++) { + if (i < nbbar) + bar[i] = '='; + else bar[i] = ' '; + } + sprintf(buffer, "|%s %c %2.1f%%", bar, rotator[last_car], percent); + last_car = (last_car + 1) % 4; + } + else { + sprintf(buffer, "%d %d %d %s", current_pass, pos, max, cur_device); + } + ui_print_text(buffer); + } +} + +void ui_set_device(char *device) +{ + cur_device = device; +} \ No newline at end of file diff --git a/src/ui.h b/src/ui.h new file mode 100644 index 0000000..5595aa1 --- /dev/null +++ b/src/ui.h @@ -0,0 +1,28 @@ +/* ui.h - Functions for handling the UI interface + + Copyright (C) 2013 Manoel Trapier + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + On Debian systems, the complete text of the GNU General Public License + can be found in /usr/share/common-licenses/GPL-3 file. +*/ + +#ifndef _UI_H +#define _UI_H + +void ui_print_new_pass(char *text); +void ui_print_progress(int pos, int max); +void ui_set_device(char *device); +#endif \ No newline at end of file