https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b0bf7dfb62400227e8fb33fbeafcb0da02145439

commit b0bf7dfb62400227e8fb33fbeafcb0da02145439
Author: Pierre Schweitzer <pie...@reactos.org>
AuthorDate: Sun Dec 17 13:59:20 2017 +0100

    [VFATLIB] Never touch the file system if not in interactive or RW mode.
    It's critical not to perform any write on a volume without an exclusive 
lock on it.
    That lock is only acquired if ChkDsk is started in RW mode.
    Also added an assert in write routine, to make sure that when we're about 
to perform
    a write operation, we're really allowed to do so.
    
    This will avoid volume corruptions when a simple "chkdsk" is issued from 
cmd.
    To put it simple: check will really check now, and won't attempt any repair.
    
    CORE-14119
---
 sdk/lib/fslib/vfatlib/check/check.c | 198 +++++++++++++++++++-----------------
 sdk/lib/fslib/vfatlib/check/fat.c   |  54 +++++-----
 sdk/lib/fslib/vfatlib/check/io.c    |   2 +
 3 files changed, 137 insertions(+), 117 deletions(-)

diff --git a/sdk/lib/fslib/vfatlib/check/check.c 
b/sdk/lib/fslib/vfatlib/check/check.c
index 5315e3684c..dcf1808687 100644
--- a/sdk/lib/fslib/vfatlib/check/check.c
+++ b/sdk/lib/fslib/vfatlib/check/check.c
@@ -493,23 +493,25 @@ static int handle_dot(DOS_FS * fs, DOS_FILE * file, int 
dots)
        if (interactive)
            printf("1) Drop it\n2) Auto-rename\n3) Rename\n"
                   "4) Convert to directory\n");
-       else
+       else if (rw)
            printf("  Auto-renaming it.\n");
-       switch (interactive ? get_key("1234", "?") : '2') {
-       case '1':
-           drop_file(fs, file);
-           return 1;
-       case '2':
-           auto_rename(file);
-           printf("  Renamed to %s\n", file_name(file->dir_ent.name));
-           return 0;
-       case '3':
-           rename_file(file);
+       if (rw || interactive) {
+               switch (interactive ? get_key("1234", "?") : '2') {
+               case '1':
+                   drop_file(fs, file);
+                   return 1;
+               case '2':
+                   auto_rename(file);
+                   printf("  Renamed to %s\n", file_name(file->dir_ent.name));
+                   return 0;
+               case '3':
+                   rename_file(file);
            return 0;
-       case '4':
-           MODIFY(file, size, htole32(0));
-           MODIFY(file, attr, file->dir_ent.attr | ATTR_DIR);
-           break;
+               case '4':
+                   MODIFY(file, size, htole32(0));
+                   MODIFY(file, attr, file->dir_ent.attr | ATTR_DIR);
+                   break;
+               }
        }
     }
     if (!dots) {
@@ -528,9 +530,9 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
 
     if (file->dir_ent.attr & ATTR_DIR) {
        if (le32toh(file->dir_ent.size)) {
-           printf("%s\n  Directory has non-zero size. Fixing it.\n",
-                  path_name(file));
-           MODIFY(file, size, htole32(0));
+           printf("%s\n  Directory has non-zero size.%s\n",
+                  path_name(file), (rw) ? " Fixing it." : "");
+           if (rw) MODIFY(file, size, htole32(0));
        }
        if (file->parent
            && !strncmp((const char *)file->dir_ent.name, MSDOS_DOT,
@@ -539,7 +541,7 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
            if (FSTART(file, fs) != expect) {
                printf("%s\n  Start (%lu) does not point to parent (%lu)\n",
                       path_name(file), (unsigned long)FSTART(file, fs), 
(long)expect);
-               MODIFY_START(file, expect, fs);
+               if (rw) MODIFY_START(file, expect, fs);
            }
            return 0;
        }
@@ -553,14 +555,14 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
            if (FSTART(file, fs) != expect) {
                printf("%s\n  Start (%lu) does not point to .. (%lu)\n",
                       path_name(file), (unsigned long)FSTART(file, fs), 
(unsigned long)expect);
-               MODIFY_START(file, expect, fs);
+               if (rw) MODIFY_START(file, expect, fs);
            }
            return 0;
        }
        if (FSTART(file, fs) == 0) {
-           printf("%s\n Start does point to root directory. Deleting dir. \n",
-                  path_name(file));
-           MODIFY(file, name[0], DELETED_FLAG);
+           printf("%s\n Start does point to root directory.%s\n",
+                  path_name(file), (rw) ? " Deleting dir. " : "");
+           if (rw) MODIFY(file, name[0], DELETED_FLAG);
            return 0;
        }
     }
@@ -569,18 +571,19 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
               path_name(file));
        if (!file->offset)
            die("Bad FAT32 root directory! (bad start cluster 1)\n");
-       MODIFY_START(file, 0, fs);
+       if (rw) MODIFY_START(file, 0, fs);
     }
     if (FSTART(file, fs) >= fs->data_clusters + 2) {
        printf
-           ("%s\n  Start cluster beyond limit (%lu > %lu). Truncating file.\n",
+           ("%s\n  Start cluster beyond limit (%lu > %lu).%s\n",
             path_name(file), (unsigned long)FSTART(file, fs),
-            (unsigned long)(fs->data_clusters + 1));
+            (unsigned long)(fs->data_clusters + 1),
+            (rw) ? " Truncating file." : "");
        if (!file->offset)
            die("Bad FAT32 root directory! (start cluster beyond limit: %lu > 
%lu)\n",
                (unsigned long)FSTART(file, fs),
                (unsigned long)(fs->data_clusters + 1));
-       MODIFY_START(file, 0, fs);
+       if (rw) MODIFY_START(file, 0, fs);
     }
     clusters = prev = 0;
     for (curr = FSTART(file, fs) ? FSTART(file, fs) :
@@ -589,25 +592,34 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
        get_fat(&curEntry, fs->fat, curr, fs);
 
        if (!curEntry.value || bad_cluster(fs, curr)) {
-           printf("%s\n  Contains a %s cluster (%lu). Assuming EOF.\n",
-                  path_name(file), curEntry.value ? "bad" : "free", (unsigned 
long)curr);
+           printf("%s\n  Contains a %s cluster (%lu).%s\n",
+                  path_name(file), curEntry.value ? "bad" : "free", (unsigned 
long)curr,
+                  (rw) ? " Assuming EOF." : "");
            if (prev)
                set_fat(fs, prev, -1);
            else if (!file->offset)
                die("FAT32 root dir starts with a bad cluster!");
            else
-               MODIFY_START(file, 0, fs);
+               if (rw) MODIFY_START(file, 0, fs);
            break;
        }
        if (!(file->dir_ent.attr & ATTR_DIR) && le32toh(file->dir_ent.size) <=
            (uint64_t)clusters * fs->cluster_size) {
-           printf
-               ("%s\n  File size is %u bytes, cluster chain length is > %llu "
-                "bytes.\n  Truncating file to %u bytes.\n", path_name(file),
-                le32toh(file->dir_ent.size),
-                (unsigned long long)clusters * fs->cluster_size,
-                le32toh(file->dir_ent.size));
-           truncate_file(fs, file, clusters);
+           if (rw) {
+                   printf
+                       ("%s\n  File size is %u bytes, cluster chain length is 
> %llu "
+                        "bytes.\n  Truncating file to %u bytes.\n", 
path_name(file),
+                        le32toh(file->dir_ent.size),
+                        (unsigned long long)clusters * fs->cluster_size,
+                        le32toh(file->dir_ent.size));
+                   truncate_file(fs, file, clusters);
+           } else {
+                   printf
+                       ("%s\n  File size is %u bytes, cluster chain length is 
> %llu "
+                        "bytes.\n", path_name(file),
+                        le32toh(file->dir_ent.size),
+                        (unsigned long long)clusters * fs->cluster_size);
+           }
            break;
        }
        if ((owner = get_owner(fs, curr))) {
@@ -622,12 +634,12 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
                else
                    clusters2++;
            restart = file->dir_ent.attr & ATTR_DIR;
-           if (!owner->offset) {
+           if (!owner->offset && rw) {
                printf("  Truncating second to %llu bytes because first "
                       "is FAT32 root dir.\n",
                       (unsigned long long)clusters2 * fs->cluster_size);
                do_trunc = 2;
-           } else if (!file->offset) {
+           } else if (!file->offset && rw) {
                printf("  Truncating first to %llu bytes because second "
                       "is FAT32 root dir.\n",
                       (unsigned long long)clusters * fs->cluster_size);
@@ -638,11 +650,11 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
                       (unsigned long long)clusters * fs->cluster_size,
                       restart ? " and restart" : "",
                       (unsigned long long)clusters2 * fs->cluster_size);
-           else
+           else if (rw)
                printf("  Truncating second to %llu bytes.\n",
                       (unsigned long long)clusters2 * fs->cluster_size);
-           if (do_trunc != 2
-               && (do_trunc == 1
+           if ((do_trunc != 2 && rw)
+               && ((do_trunc == 1 && rw)
                    || (interactive && get_key("12", "?") == '1'))) {
                prev = 0;
                clusters = 0;
@@ -684,7 +696,7 @@ static int check_file(DOS_FS * fs, DOS_FILE * file)
        prev = curr;
     }
     if (!(file->dir_ent.attr & ATTR_DIR) && le32toh(file->dir_ent.size) >
-       (uint64_t)clusters * fs->cluster_size) {
+       (uint64_t)clusters * fs->cluster_size && rw) {
        printf
            ("%s\n  File size is %u bytes, cluster chain length is %llu bytes."
             "\n  Truncating file to %llu bytes.\n", path_name(file),
@@ -727,7 +739,7 @@ static int check_dir(DOS_FS * fs, DOS_FILE ** root, int 
dots)
               path_name(parent), bad, good + bad);
        if (!dots)
            printf("  Not dropping root directory.\n");
-       else if (!interactive)
+       else if (!interactive || !rw)
            printf("  Not dropping it in auto-mode.\n");
        else if (get_key("yn", "Drop directory ? (y/n)") == 'y') {
            truncate_file(fs, parent, 0);
@@ -759,23 +771,25 @@ static int check_dir(DOS_FS * fs, DOS_FILE ** root, int 
dots)
            if (interactive)
                printf("1) Drop file\n2) Rename file\n3) Auto-rename\n"
                       "4) Keep it\n");
-           else
+           else if (rw)
                printf("  Auto-renaming it.\n");
-           switch (interactive ? get_key("1234", "?") : '3') {
-           case '1':
-               drop_file(fs, *walk);
-               walk = &(*walk)->next;
-               continue;
-           case '2':
-               rename_file(*walk);
-               redo = 1;
-               break;
-           case '3':
-               auto_rename(*walk);
-               printf("  Renamed to %s\n", file_name((*walk)->dir_ent.name));
-               break;
-           case '4':
-               break;
+           if (rw || interactive) {
+                   switch (interactive ? get_key("1234", "?") : '3') {
+                   case '1':
+                       drop_file(fs, *walk);
+                       walk = &(*walk)->next;
+                       continue;
+                   case '2':
+                       rename_file(*walk);
+                       redo = 1;
+                       break;
+                   case '3':
+                       auto_rename(*walk);
+                       printf("  Renamed to %s\n", 
file_name((*walk)->dir_ent.name));
+                       break;
+                   case '4':
+                       break;
+                   }
            }
        }
        /* don't check for duplicates of the volume label */
@@ -794,38 +808,40 @@ static int check_dir(DOS_FS * fs, DOS_FILE ** root, int 
dots)
                            ("1) Drop first\n2) Drop second\n3) Rename first\n"
                             "4) Rename second\n5) Auto-rename first\n"
                             "6) Auto-rename second\n");
-                   else
+                   else if (rw)
                        printf("  Auto-renaming second.\n");
-                   switch (interactive ? get_key("123456", "?") : '6') {
-                   case '1':
-                       drop_file(fs, *walk);
-                       *walk = (*walk)->next;
-                       skip = 1;
-                       break;
-                   case '2':
-                       drop_file(fs, *scan);
-                       *scan = (*scan)->next;
-                       continue;
-                   case '3':
-                       rename_file(*walk);
-                       printf("  Renamed to %s\n", path_name(*walk));
-                       redo = 1;
-                       break;
-                   case '4':
-                       rename_file(*scan);
-                       printf("  Renamed to %s\n", path_name(*walk));
-                       redo = 1;
-                       break;
-                   case '5':
-                       auto_rename(*walk);
-                       printf("  Renamed to %s\n",
-                              file_name((*walk)->dir_ent.name));
-                       break;
-                   case '6':
-                       auto_rename(*scan);
-                       printf("  Renamed to %s\n",
-                              file_name((*scan)->dir_ent.name));
-                       break;
+                   if (rw || interactive) {
+                           switch (interactive ? get_key("123456", "?") : '6') 
{
+                           case '1':
+                               drop_file(fs, *walk);
+                               *walk = (*walk)->next;
+                               skip = 1;
+                               break;
+                           case '2':
+                               drop_file(fs, *scan);
+                               *scan = (*scan)->next;
+                               continue;
+                           case '3':
+                               rename_file(*walk);
+                               printf("  Renamed to %s\n", path_name(*walk));
+                               redo = 1;
+                               break;
+                           case '4':
+                               rename_file(*scan);
+                               printf("  Renamed to %s\n", path_name(*walk));
+                               redo = 1;
+                               break;
+                           case '5':
+                               auto_rename(*walk);
+                               printf("  Renamed to %s\n",
+                                      file_name((*walk)->dir_ent.name));
+                               break;
+                           case '6':
+                               auto_rename(*scan);
+                               printf("  Renamed to %s\n",
+                                      file_name((*scan)->dir_ent.name));
+                               break;
+                           }
                    }
                }
                scan = &(*scan)->next;
diff --git a/sdk/lib/fslib/vfatlib/check/fat.c 
b/sdk/lib/fslib/vfatlib/check/fat.c
index 87c7fa5f2b..a601e6a67f 100644
--- a/sdk/lib/fslib/vfatlib/check/fat.c
+++ b/sdk/lib/fslib/vfatlib/check/fat.c
@@ -350,7 +350,7 @@ void reclaim_free(DOS_FS * fs)
        get_fat(&curEntry, fs->fat, i, fs);
 
        if (!get_owner(fs, i) && curEntry.value &&
-           !FAT_IS_BAD(fs, curEntry.value)) {
+           !FAT_IS_BAD(fs, curEntry.value) && rw) {
            set_fat(fs, i, 0);
            reclaimed++;
        }
@@ -490,30 +490,32 @@ void reclaim_file(DOS_FS * fs)
     }
     while (changed);
 
-    /* Now we can start recovery */
-    files = reclaimed = 0;
-    for (i = 2; i < total_num_clusters; i++)
-       /* If this cluster is the head of an orphan chain... */
-       if (get_owner(fs, i) == &orphan && !num_refs[i]) {
-           DIR_ENT de;
-           off_t offset;
-           files++;
-           offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC");
-           de.start = htole16(i & 0xffff);
-           if (fs->fat_bits == 32)
-               de.starthi = htole16(i >> 16);
-           for (walk = i; walk > 0 && walk != -1;
-                walk = next_cluster(fs, walk)) {
-               de.size = htole32(le32toh(de.size) + fs->cluster_size);
-               reclaimed++;
+    if (rw) {
+        /* Now we can start recovery */
+        files = reclaimed = 0;
+        for (i = 2; i < total_num_clusters; i++)
+           /* If this cluster is the head of an orphan chain... */
+           if (get_owner(fs, i) == &orphan && !num_refs[i]) {
+               DIR_ENT de;
+               off_t offset;
+               files++;
+               offset = alloc_rootdir_entry(fs, &de, "FSCK%04dREC");
+               de.start = htole16(i & 0xffff);
+               if (fs->fat_bits == 32)
+                   de.starthi = htole16(i >> 16);
+               for (walk = i; walk > 0 && walk != -1;
+                    walk = next_cluster(fs, walk)) {
+                   de.size = htole32(le32toh(de.size) + fs->cluster_size);
+                   reclaimed++;
+               }
+               fs_write(offset, sizeof(DIR_ENT), &de);
            }
-           fs_write(offset, sizeof(DIR_ENT), &de);
-       }
-    if (reclaimed)
-       printf("Reclaimed %d unused cluster%s (%llu bytes) in %d chain%s.\n",
-              reclaimed, reclaimed == 1 ? "" : "s",
-              (unsigned long long)reclaimed * fs->cluster_size, files,
-              files == 1 ? "" : "s");
+        if (reclaimed)
+           printf("Reclaimed %d unused cluster%s (%llu bytes) in %d 
chain%s.\n",
+                  reclaimed, reclaimed == 1 ? "" : "s",
+                  (unsigned long long)reclaimed * fs->cluster_size, files,
+                  files == 1 ? "" : "s");
+    }
 
     free(num_refs);
 }
@@ -543,9 +545,9 @@ uint32_t update_free(DOS_FS * fs)
                   (long)fs->free_clusters, (long)free);
            if (interactive)
                printf("1) Correct\n2) Don't correct\n");
-           else
+           else if (rw)
                printf("  Auto-correcting.\n");
-           if (!interactive || get_key("12", "?") == '1')
+           if ((!interactive && rw) || (interactive && get_key("12", "?") == 
'1'))
                do_set = 1;
        }
     } else {
diff --git a/sdk/lib/fslib/vfatlib/check/io.c b/sdk/lib/fslib/vfatlib/check/io.c
index 2eca2abdd4..06e0496e1a 100644
--- a/sdk/lib/fslib/vfatlib/check/io.c
+++ b/sdk/lib/fslib/vfatlib/check/io.c
@@ -352,6 +352,8 @@ void fs_write(off_t pos, int size, void *data)
     CHANGE *new;
     int did;
 
+    assert(interactive || rw);
+
 #if 1 //SAE
 
     if (FsCheckFlags & FSCHECK_IMMEDIATE_WRITE) {

Reply via email to