"Fossies" - the Fresh Open Source Software Archive

Member "dosfstools-4.2/src/fsck.fat.c" (31 Jan 2021, 8413 Bytes) of package /linux/misc/dosfstools-4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "fsck.fat.c": 4.1_vs_4.2.

    1 /* fsck.fat.c - User interface
    2 
    3    Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch>
    4    Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
    5    Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch>
    6    Copyright (C) 2018-2021 Pali Rohár <pali.rohar@gmail.com>
    7 
    8    This program is free software: you can redistribute it and/or modify
    9    it under the terms of the GNU General Public License as published by
   10    the Free Software Foundation, either version 3 of the License, or
   11    (at your option) any later version.
   12 
   13    This program is distributed in the hope that it will be useful,
   14    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   16    GNU General Public License for more details.
   17 
   18    You should have received a copy of the GNU General Public License
   19    along with this program. If not, see <http://www.gnu.org/licenses/>.
   20 
   21    The complete text of the GNU General Public License
   22    can be found in /usr/share/common-licenses/GPL-3 file.
   23 */
   24 
   25 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
   26  * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
   27 
   28 #include "version.h"
   29 
   30 #include <stdio.h>
   31 #include <stdlib.h>
   32 #include <string.h>
   33 #include <stdlib.h>
   34 #include <errno.h>
   35 #include <ctype.h>
   36 #include <limits.h>
   37 #include <unistd.h>
   38 #include <termios.h>
   39 #include <getopt.h>
   40 
   41 #include "common.h"
   42 #include "fsck.fat.h"
   43 #include "io.h"
   44 #include "boot.h"
   45 #include "fat.h"
   46 #include "file.h"
   47 #include "check.h"
   48 #include "charconv.h"
   49 
   50 int rw = 0, list = 0, test = 0, verbose = 0;
   51 long fat_table = 0;
   52 int no_spaces_in_sfns = 0;
   53 int only_uppercase_label = 0;
   54 int boot_only = 0;
   55 unsigned n_files = 0;
   56 void *mem_queue = NULL;
   57 
   58 static struct termios original_termios;
   59 
   60 
   61 static void restore_termios(void)
   62 {
   63     tcsetattr(0, TCSAFLUSH, &original_termios);
   64 }
   65 
   66 
   67 static void usage(char *name, int exitval)
   68 {
   69     fprintf(stderr, "Usage: %s [OPTIONS] DEVICE\n", name);
   70     fprintf(stderr, "Check FAT filesystem on DEVICE for errors.\n");
   71     fprintf(stderr, "\n");
   72     fprintf(stderr, "Options:\n");
   73     fprintf(stderr, "  -a              automatically repair the filesystem\n");
   74     fprintf(stderr, "  -A              toggle Atari variant of the FAT filesystem\n");
   75     fprintf(stderr, "  -b              make read-only boot sector check\n");
   76     fprintf(stderr, "  -c N            use DOS codepage N to decode short file names (default: %d)\n",
   77         DEFAULT_DOS_CODEPAGE);
   78     fprintf(stderr, "  -d PATH         drop file with name PATH (can be given multiple times)\n");
   79     fprintf(stderr, "  -f              salvage unused chains to files\n");
   80     fprintf(stderr, "  -F NUM          specify FAT table NUM used for filesystem access\n");
   81     fprintf(stderr, "  -l              list path names\n");
   82     fprintf(stderr, "  -n              no-op, check non-interactively without changing\n");
   83     fprintf(stderr, "  -p              same as -a, for compat with other *fsck\n");
   84     fprintf(stderr, "  -r              interactively repair the filesystem (default)\n");
   85     fprintf(stderr, "  -S              disallow spaces in the middle of short file names\n");
   86     fprintf(stderr, "  -t              test for bad clusters\n");
   87     fprintf(stderr, "  -u PATH         try to undelete (non-directory) file that was named PATH (can be\n");
   88     fprintf(stderr, "                    given multiple times)\n");
   89     fprintf(stderr, "  -U              allow only uppercase characters in volume and boot label\n");
   90     fprintf(stderr, "  -v              verbose mode\n");
   91     fprintf(stderr, "  -V              perform a verification pass\n");
   92     fprintf(stderr, "  --variant=TYPE  handle variant TYPE of the filesystem\n");
   93     fprintf(stderr, "  -w              write changes to disk immediately\n");
   94     fprintf(stderr, "  -y              same as -a, for compat with other *fsck\n");
   95     fprintf(stderr, "  --help          print this message\n");
   96     exit(exitval);
   97 }
   98 
   99 int main(int argc, char **argv)
  100 {
  101     DOS_FS fs;
  102     int salvage_files, verify, c;
  103     uint32_t free_clusters = 0;
  104     struct termios tio;
  105     char *tmp;
  106     long codepage;
  107 
  108     enum {OPT_HELP=1000, OPT_VARIANT};
  109     const struct option long_options[] = {
  110         {"variant", required_argument, NULL, OPT_VARIANT},
  111         {"help",    no_argument,       NULL, OPT_HELP},
  112         {0,}
  113     };
  114 
  115     if (!tcgetattr(0, &original_termios)) {
  116     tio = original_termios;
  117     tio.c_lflag &= ~(ICANON | ECHO);
  118     tcsetattr(0, TCSAFLUSH, &tio);
  119     atexit(restore_termios);
  120     }
  121 
  122     memset(&fs, 0, sizeof(fs));
  123     salvage_files = verify = 0;
  124     rw = interactive = 1;
  125     check_atari();
  126 
  127     while ((c = getopt_long(argc, argv, "Aac:d:bfF:lnprStu:UvVwy",
  128                     long_options, NULL)) != -1)
  129     switch (c) {
  130     case 'A':       /* toggle Atari format */
  131         atari_format = !atari_format;
  132         break;
  133     case 'a':
  134     case 'p':
  135     case 'y':
  136         rw = 1;
  137         interactive = 0;
  138         salvage_files = 1;
  139         break;
  140     case 'b':
  141         rw = 0;
  142         interactive = 0;
  143         boot_only = 1;
  144         break;
  145     case 'c':
  146         errno = 0;
  147         codepage = strtol(optarg, &tmp, 10);
  148         if (!*optarg || isspace(*optarg) || *tmp || errno || codepage < 0 || codepage > INT_MAX) {
  149         fprintf(stderr, "Invalid codepage : %s\n", optarg);
  150         usage(argv[0], 2);
  151         }
  152         if (!set_dos_codepage(codepage))
  153         usage(argv[0], 2);
  154         break;
  155     case 'd':
  156         file_add(optarg, fdt_drop);
  157         break;
  158     case 'f':
  159         salvage_files = 1;
  160         break;
  161     case 'F':
  162         errno = 0;
  163         fat_table = strtol(optarg, &tmp, 10);
  164         if (!*optarg || isspace(*optarg) || *tmp || errno || fat_table < 0 || fat_table > 255) {
  165         fprintf(stderr, "Invalid FAT table : %s\n", optarg);
  166         usage(argv[0], 2);
  167         }
  168         break;
  169     case 'l':
  170         list = 1;
  171         break;
  172     case 'n':
  173         rw = 0;
  174         interactive = 0;
  175         break;
  176     case 'r':
  177         rw = 1;
  178         interactive = 1;
  179         break;
  180     case 'S':
  181         no_spaces_in_sfns = 1;
  182         break;
  183     case 't':
  184         test = 1;
  185         break;
  186     case 'u':
  187         file_add(optarg, fdt_undelete);
  188         break;
  189     case 'U':
  190         only_uppercase_label = 1;
  191         break;
  192     case 'v':
  193         verbose = 1;
  194         break;
  195     case 'V':
  196         verify = 1;
  197         break;
  198     case OPT_VARIANT:
  199         if (!strcasecmp(optarg, "standard")) {
  200             atari_format = 0;
  201         } else if (!strcasecmp(optarg, "atari")) {
  202             atari_format = 1;
  203         } else {
  204             fprintf(stderr, "Unknown variant: %s\n", optarg);
  205             usage(argv[0], 2);
  206         }
  207         break;
  208     case 'w':
  209         write_immed = 1;
  210         break;
  211     case OPT_HELP:
  212         usage(argv[0], 0);
  213         break;
  214     case '?':
  215         usage(argv[0], 2);
  216         break;
  217     default:
  218         fprintf(stderr,
  219             "Internal error: getopt_long() returned unexpected value %d\n", c);
  220         exit(3);
  221     }
  222     if (!set_dos_codepage(-1))  /* set default codepage if none was given in command line */
  223         exit(2);
  224     if ((test || write_immed) && !rw) {
  225     fprintf(stderr, "-t and -w can not be used in read only mode\n");
  226     exit(2);
  227     }
  228     if (optind != argc - 1)
  229     usage(argv[0], 2);
  230 
  231     printf("fsck.fat " VERSION " (" VERSION_DATE ")\n");
  232     fs_open(argv[optind], rw);
  233 
  234     read_boot(&fs);
  235     if (boot_only)
  236     goto exit;
  237 
  238     if (verify)
  239     printf("Starting check/repair pass.\n");
  240     while (read_fat(&fs, 2), scan_root(&fs))
  241     qfree(&mem_queue);
  242     check_label(&fs);
  243     if (test)
  244     fix_bad(&fs);
  245     if (salvage_files)
  246     reclaim_file(&fs);
  247     else
  248     reclaim_free(&fs);
  249     if (!atari_format)
  250     check_dirty_bits(&fs);
  251     free_clusters = update_free(&fs);
  252     file_unused();
  253     qfree(&mem_queue);
  254     if (verify) {
  255     n_files = 0;
  256     printf("Starting verification pass.\n");
  257     read_fat(&fs, 2);
  258     scan_root(&fs);
  259     check_label(&fs);
  260     reclaim_free(&fs);
  261     if (!atari_format)
  262         check_dirty_bits(&fs);
  263     qfree(&mem_queue);
  264     }
  265     release_fat(&fs);
  266 
  267 exit:
  268     if (!write_immed && fs_changed()) {
  269     if (rw) {
  270         printf("\n*** Filesystem was changed ***\n");
  271         if (interactive)
  272         printf("The changes have not yet been written, you can still choose to leave the\n"
  273                "filesystem unmodified:\n");
  274 
  275         rw = get_choice(1, "Writing changes.",
  276                 2,
  277                 1, "Write changes",
  278                 2, "Leave filesystem unchanged") == 1;
  279     } else
  280         printf("\nLeaving filesystem unchanged.\n");
  281     }
  282 
  283     if (!boot_only)
  284     printf("%s: %u files, %lu/%lu clusters\n", argv[optind],
  285            n_files, (unsigned long)fs.data_clusters - free_clusters,
  286            (unsigned long)fs.data_clusters);
  287 
  288     return fs_close(rw) ? 1 : 0;
  289 }