Browse Source

Add UI definition, and preliminary support on major check loops.

Godzil 11 years ago
parent
commit
559fd817ef
6 changed files with 171 additions and 11 deletions
  1. 2 2
      Makefile
  2. 6 2
      src/check.c
  3. 35 7
      src/dosfsck.c
  4. 2 0
      src/fat.c
  5. 98 0
      src/ui.c
  6. 28 0
      src/ui.h

+ 2 - 2
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
 

+ 6 - 2
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);

+ 35 - 7
src/dosfsck.c

@@ -3,6 +3,7 @@
    Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
    Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
    Copyright (C) 2008-2013 Daniel Baumann <mail@daniel-baumann.ch>
+   Copyright (C) 2013 Manoel Trapier <godzil@godzil.net>
 
    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");
+    /* 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");
     }

+ 2 - 0
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) {

+ 98 - 0
src/ui.c

@@ -0,0 +1,98 @@
+/* ui.c - Functions for handling the UI interface
+
+   Copyright (C) 2013 Manoel Trapier <godzil@godzil.net>
+
+   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 <http://www.gnu.org/licenses/>.
+
+   On Debian systems, the complete text of the GNU General Public License
+   can be found in /usr/share/common-licenses/GPL-3 file.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <unistd.h>
+
+#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;
+}

+ 28 - 0
src/ui.h

@@ -0,0 +1,28 @@
+/* ui.h - Functions for handling the UI interface
+
+   Copyright (C) 2013 Manoel Trapier <godzil@godzil.net>
+
+   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 <http://www.gnu.org/licenses/>.
+
+   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