sbin/fsck_msdosfs: Bring in freebsd/freebsd@53d879fa (mix of unrelated changes...)
authorTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Sat, 14 Sep 2019 19:59:49 +0000 (04:59 +0900)
committerTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Sat, 14 Sep 2019 22:57:20 +0000 (07:57 +0900)
sbin/fsck_msdosfs/boot.c
sbin/fsck_msdosfs/check.c
sbin/fsck_msdosfs/dir.c
sbin/fsck_msdosfs/ext.h
sbin/fsck_msdosfs/fat.c
sbin/fsck_msdosfs/main.c

index 42c5bf7..aae40b0 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -41,8 +40,9 @@ readboot(int dosfs, struct bootblock *boot)
        u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
        u_char backup[DOSBOOTBLOCKSIZE];
        int ret = FSOK;
+       int i;
 
-       if (read(dosfs, block, sizeof block) < sizeof block) {
+       if ((size_t)read(dosfs, block, sizeof block) != sizeof block) {
                perr("could not read boot block");
                return FSFATAL;
        }
@@ -146,9 +146,22 @@ readboot(int dosfs, struct bootblock *boot)
                        return FSFATAL;
                }
                if (memcmp(block, backup, DOSBOOTBLOCKSIZE)) {
-                       /* Correct?                                     XXX */
-                       pfatal("backup doesn't compare to primary bootblock");
-                       return FSFATAL;
+                       /*
+                        * XXX We require a reference that explains
+                        * that these bytes need to match, or should
+                        * drop the check.  gdt@NetBSD has observed
+                        * filesystems that work fine under Windows XP
+                        * and NetBSD that do not match, so the
+                        * requirement is suspect.  For now, just
+                        * print out useful information and continue.
+                        */
+                       pfatal("backup (block %d) mismatch with primary bootblock:\n",
+                               boot->bpbBackup);
+                       for (i = 11; i < 11 + 90; i++) {
+                               if (block[i] != backup[i])
+                                       pfatal("\ti=%d\tprimary 0x%02x\tbackup 0x%02x\n",
+                                              i, block[i], backup[i]);
+                       }
                }
                /* Check backup bpbFSInfo?                                      XXX */
        }
index c8733f1..46358f7 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -41,7 +40,8 @@ checkfilesys(const char *fname)
        int dosfs;
        struct bootblock boot;
        struct fatEntry *fat = NULL;
-       int i, finish_dosdirsection=0;
+       int finish_dosdirsection=0;
+       u_int i;
        int mod = 0;
        int ret = 8;
 
index 5a44095..2d6dda7 100644 (file)
@@ -220,12 +220,24 @@ resetDosDirSection(struct bootblock *boot, struct fatEntry *fat)
        b1 = boot->bpbRootDirEnts * 32;
        b2 = boot->bpbSecPerClust * boot->bpbBytesPerSec;
 
-       if (!(buffer = malloc(b1 > b2 ? b1 : b2))
-           || !(delbuf = malloc(b2))
-           || !(rootDir = newDosDirEntry())) {
+       if ((buffer = malloc( b1 > b2 ? b1 : b2)) == NULL) {
                perr("No space for directory buffer");
                return FSFATAL;
        }
+
+       if ((delbuf = malloc(b2)) == NULL) {
+               free(buffer);
+               perr("No space for directory delbuf");
+               return FSFATAL;
+       }
+
+       if ((rootDir = newDosDirEntry()) == NULL) {
+               free(buffer);
+               free(delbuf);
+               perr("No space for directory entry");
+               return FSFATAL;
+       }
+
        memset(rootDir, 0, sizeof *rootDir);
        if (boot->flags & FAT32) {
                if (boot->bpbRootClust < CLUST_FIRST || boot->bpbRootClust >= boot->NumClusters) {
@@ -358,7 +370,8 @@ removede(int f, struct bootblock *boot, struct fatEntry *fat, u_char *start,
                                return FSFATAL;
                        start = buffer;
                }
-               if (endcl == curcl)
+               /* startcl is < CLUST_FIRST for !fat32 root */
+               if ((endcl == curcl) || (startcl < CLUST_FIRST))
                        for (; start < end; start += 32)
                                *start = SLOT_DELETED;
                return FSDIRMOD;
@@ -376,7 +389,7 @@ checksize(struct bootblock *boot, struct fatEntry *fat, u_char *p,
        /*
         * Check size on ordinary files
         */
-       int32_t physicalSize;
+       u_int32_t physicalSize;
 
        if (dir->head == CLUST_FREE)
                physicalSize = 0;
@@ -710,7 +723,8 @@ readDosDirSection(int f, struct bootblock *boot, struct fatEntry *fat,
                                dirent.head |= (p[20] << 16) | (p[21] << 24);
                        dirent.size = p[28] | (p[29] << 8) | (p[30] << 16) | (p[31] << 24);
                        if (vallfn) {
-                               strcpy(dirent.lname, longName);
+                               strlcpy(dirent.lname, longName,
+                                   sizeof(dirent.lname));
                                longName[0] = '\0';
                                shortSum = -1;
                        }
@@ -928,6 +942,10 @@ readDosDirSection(int f, struct bootblock *boot, struct fatEntry *fat,
                        }
                        boot->NumFiles++;
                }
+
+               if (!(boot->flags & FAT32) && !dir->parent)
+                       break;
+
                if (mod & THISMOD) {
                        last *= 32;
                        if (lseek(f, off, SEEK_SET) != off
@@ -943,6 +961,19 @@ readDosDirSection(int f, struct bootblock *boot, struct fatEntry *fat,
                                invlfn ? invlfn : vallfn, p,
                                invlfn ? invcl : valcl, -1, 0,
                                fullpath(dir), 1);
+
+       /* The root directory of non fat32 filesystems is in a special
+        * area and may have been modified above without being written out.
+        */
+       if ((mod & FSDIRMOD) && !(boot->flags & FAT32) && !dir->parent) {
+               last *= 32;
+               if (lseek(f, off, SEEK_SET) != off
+                   || write(f, buffer, last) != last) {
+                       perr("Unable to write directory");
+                       return FSFATAL;
+               }
+               mod &= ~THISMOD;
+       }
        return mod & ~THISMOD;
 }
 
@@ -1032,7 +1063,7 @@ reconnect(int dosfs, struct bootblock *boot, struct fatEntry *fat, cl_t head)
                lfoff = lfcl * boot->ClusterSize
                    + boot->ClusterOffset * boot->bpbBytesPerSec;
                if (lseek(dosfs, lfoff, SEEK_SET) != lfoff
-                   || read(dosfs, lfbuf, boot->ClusterSize) != boot->ClusterSize) {
+                   || (size_t)read(dosfs, lfbuf, boot->ClusterSize) != boot->ClusterSize) {
                        perr("could not read LOST.DIR");
                        return FSFATAL;
                }
@@ -1062,7 +1093,7 @@ reconnect(int dosfs, struct bootblock *boot, struct fatEntry *fat, cl_t head)
        p[31] = (u_char)(d.size >> 24);
        fat[head].flags |= FAT_USED;
        if (lseek(dosfs, lfoff, SEEK_SET) != lfoff
-           || write(dosfs, lfbuf, boot->ClusterSize) != boot->ClusterSize) {
+           || (size_t)write(dosfs, lfbuf, boot->ClusterSize) != boot->ClusterSize) {
                perr("could not write LOST.DIR");
                return FSFATAL;
        }
index 0c417ec..00cd708 100644 (file)
@@ -64,12 +64,12 @@ int checkfilesys(const char *);
 #define        FSDIRMOD        2               /* Some directory was modified */
 #define        FSFATMOD        4               /* The FAT was modified */
 #define        FSERROR         8               /* Some unrecovered error remains */
-#define        FSFATAL         16              /* Some unrecoverable error occured */
+#define        FSFATAL         16              /* Some unrecoverable error occurred */
 #define FSDIRTY                32              /* File system is dirty */
 #define FSFIXFAT       64              /* Fix file system FAT */
 
 /*
- * read a boot block in a machine independend fashion and translate
+ * read a boot block in a machine independent fashion and translate
  * it into our struct bootblock.
  */
 int readboot(int, struct bootblock *);
@@ -83,13 +83,13 @@ int writefsinfo(int, struct bootblock *);
  * Read one of the FAT copies and return a pointer to the new
  * allocated array holding our description of it.
  */
-int readfat(int, struct bootblock *, int, struct fatEntry **);
+int readfat(int, struct bootblock *, u_int, struct fatEntry **);
 
 /*
  * Check two FAT copies for consistency and merge changes into the
- * first if neccessary.
+ * first if necessary.
  */
-int comparefat(struct bootblock *, struct fatEntry *, struct fatEntry *, int);
+int comparefat(struct bootblock *, struct fatEntry *, struct fatEntry *, u_int);
 
 /*
  * Check a FAT
index f8d36eb..9f92ceb 100644 (file)
 #include "ext.h"
 #include "fsutil.h"
 
-static int checkclnum(struct bootblock *, int, cl_t, cl_t *);
-static int clustdiffer(cl_t, cl_t *, cl_t *, int);
+static int checkclnum(struct bootblock *, u_int, cl_t, cl_t *);
+static int clustdiffer(cl_t, cl_t *, cl_t *, u_int);
 static int tryclear(struct bootblock *, struct fatEntry *, cl_t, cl_t *);
-static int _readfat(int, struct bootblock *, int, u_char **);
+static int _readfat(int, struct bootblock *, u_int, u_char **);
 
 /*
  * Check a cluster number for valid value
  */
 static int
-checkclnum(struct bootblock *boot, int fat, cl_t cl, cl_t *next)
+checkclnum(struct bootblock *boot, u_int fat, cl_t cl, cl_t *next)
 {
        if (*next >= (CLUST_RSRVD&boot->ClustMask))
                *next |= ~boot->ClustMask;
@@ -74,7 +74,7 @@ checkclnum(struct bootblock *boot, int fat, cl_t cl, cl_t *next)
  * Read a FAT from disk. Returns 1 if successful, 0 otherwise.
  */
 static int
-_readfat(int fs, struct bootblock *boot, int no, u_char **buffer)
+_readfat(int fs, struct bootblock *boot, u_int no, u_char **buffer)
 {
        off_t off;
 
@@ -93,7 +93,7 @@ _readfat(int fs, struct bootblock *boot, int no, u_char **buffer)
                goto err;
        }
 
-       if (read(fs, *buffer, boot->FATsecs * boot->bpbBytesPerSec)
+       if ((size_t)read(fs, *buffer, boot->FATsecs * boot->bpbBytesPerSec)
            != boot->FATsecs * boot->bpbBytesPerSec) {
                perr("Unable to read FAT");
                goto err;
@@ -110,7 +110,7 @@ err:
  * Read a FAT and decode it into internal format
  */
 int
-readfat(int fs, struct bootblock *boot, int no, struct fatEntry **fp)
+readfat(int fs, struct bootblock *boot, u_int no, struct fatEntry **fp)
 {
        struct fatEntry *fat;
        u_char *buffer, *p;
@@ -219,7 +219,11 @@ readfat(int fs, struct bootblock *boot, int no, struct fatEntry **fp)
        }
 
        free(buffer);
-       *fp = fat;
+       if (ret & FSFATAL) {
+               free(fat);
+               *fp = NULL;
+       } else
+               *fp = fat;
        return ret;
 }
 
@@ -239,7 +243,7 @@ rsrvdcltype(cl_t cl)
 }
 
 static int
-clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum)
+clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, u_int fatnum)
 {
        if (*cp1 == CLUST_FREE || *cp1 >= CLUST_RSRVD) {
                if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) {
@@ -254,13 +258,13 @@ clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum)
                                }
                                return FSFATAL;
                        }
-                       pwarn("Cluster %u is marked %s in FAT 0, %s in FAT %d\n",
+                       pwarn("Cluster %u is marked %s in FAT 0, %s in FAT %u\n",
                              cl, rsrvdcltype(*cp1), rsrvdcltype(*cp2), fatnum);
-                       if (ask(0, "use FAT 0's entry")) {
+                       if (ask(0, "Use FAT 0's entry")) {
                                *cp2 = *cp1;
                                return FSFATMOD;
                        }
-                       if (ask(0, "use FAT %d's entry", fatnum)) {
+                       if (ask(0, "Use FAT %u's entry", fatnum)) {
                                *cp1 = *cp2;
                                return FSFATMOD;
                        }
@@ -268,7 +272,7 @@ clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum)
                }
                pwarn("Cluster %u is marked %s in FAT 0, but continues with cluster %u in FAT %d\n",
                      cl, rsrvdcltype(*cp1), *cp2, fatnum);
-               if (ask(0, "Use continuation from FAT %d", fatnum)) {
+               if (ask(0, "Use continuation from FAT %u", fatnum)) {
                        *cp1 = *cp2;
                        return FSFATMOD;
                }
@@ -279,7 +283,7 @@ clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum)
                return FSFATAL;
        }
        if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) {
-               pwarn("Cluster %u continues with cluster %u in FAT 0, but is marked %s in FAT %d\n",
+               pwarn("Cluster %u continues with cluster %u in FAT 0, but is marked %s in FAT %u\n",
                      cl, *cp1, rsrvdcltype(*cp2), fatnum);
                if (ask(0, "Use continuation from FAT 0")) {
                        *cp2 = *cp1;
@@ -291,13 +295,13 @@ clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum)
                }
                return FSERROR;
        }
-       pwarn("Cluster %u continues with cluster %u in FAT 0, but with cluster %u in FAT %d\n",
+       pwarn("Cluster %u continues with cluster %u in FAT 0, but with cluster %u in FAT %u\n",
              cl, *cp1, *cp2, fatnum);
        if (ask(0, "Use continuation from FAT 0")) {
                *cp2 = *cp1;
                return FSFATMOD;
        }
-       if (ask(0, "Use continuation from FAT %d", fatnum)) {
+       if (ask(0, "Use continuation from FAT %u", fatnum)) {
                *cp1 = *cp2;
                return FSFATMOD;
        }
@@ -310,7 +314,7 @@ clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum)
  */
 int
 comparefat(struct bootblock *boot, struct fatEntry *first,
-           struct fatEntry *second, int fatnum)
+    struct fatEntry *second, u_int fatnum)
 {
        cl_t cl;
        int ret = FSOK;
@@ -450,8 +454,8 @@ writefat(int fs, struct bootblock *boot, struct fatEntry *fat, int correct_fat)
 {
        u_char *buffer, *p;
        cl_t cl;
-       int i;
-       uint32_t fatsz;
+       u_int i;
+       size_t fatsz;
        off_t off;
        int ret = FSOK;
 
@@ -542,7 +546,7 @@ writefat(int fs, struct bootblock *boot, struct fatEntry *fat, int correct_fat)
                off = boot->bpbResSectors + i * boot->FATsecs;
                off *= boot->bpbBytesPerSec;
                if (lseek(fs, off, SEEK_SET) != off
-                   || write(fs, buffer, fatsz) != fatsz) {
+                   || (size_t)write(fs, buffer, fatsz) != fatsz) {
                        perr("Unable to write FAT");
                        ret = FSFATAL; /* Return immediately?           XXX */
                }
@@ -592,18 +596,6 @@ checklost(int dosfs, struct bootblock *boot, struct fatEntry *fat)
                                ret = 1;
                        }
                }
-               if (boot->NumFree && (boot->FSNext >= boot->NumClusters ||
-                                     fat[boot->FSNext].next != CLUST_FREE)) {
-                       pwarn("Next free cluster in FSInfo block (%u) not free\n",
-                             boot->FSNext);
-                       if (ask(1, "fix"))
-                               for (head = CLUST_FIRST; head < boot->NumClusters; head++)
-                                       if (fat[head].next == CLUST_FREE) {
-                                               boot->FSNext = head;
-                                               ret = 1;
-                                               break;
-                                       }
-               }
                if (ret)
                        mod |= writefsinfo(dosfs, boot);
        }
index 8d7e930..d11e79b 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>