On Wed, Feb 22, 2012 at 03:20:13PM -0500, Kenneth R Westerback wrote:
> On Wed, Feb 22, 2012 at 08:47:45PM +0200, Alexey Vatchenko wrote:
> > On Wed, Feb 22, 2012 at 01:16:39PM -0500, Kenneth R Westerback wrote:
> > > On Wed, Feb 22, 2012 at 06:28:19PM +0200, Alexey Vatchenko wrote:
> > > > On Wed, Feb 22, 2012 at 5:00 PM, Kenneth R Westerback
> > > > <[email protected]> wrote:
> > > > > This seems to be the difference between fsck_msdos and fsck_ffs that 
> > > > > lets
> > > > > fsck_msdos incorrectly use the block device.
> > > > >
> > > > > This still works on my 512-byte sector msdos fs and uses the raw
> > > > > device. I think it will make your fsck/fsck_msdos behaviour 
> > > > > consistant.
> > > > >
> > > > > Then we can figure out if fsck_msdos can ever work with devices of 
> > > > > sector
> > > > > sizes other than 512 bytes.
> > > > >
> > > > > Index: main.c
> > > > > ===================================================================
> > > > > RCS file: /cvs/src/sbin/fsck_msdos/main.c,v
> > > > > retrieving revision 1.17
> > > > > diff -u -p -r1.17 main.c
> > > > > --- main.c ? ? ?12 Aug 2010 15:26:34 -0000 ? ? ?1.17
> > > > > +++ main.c ? ? ?22 Feb 2012 14:42:08 -0000
> > > > > @@ -98,7 +98,7 @@ main(int argc, char *argv[])
> > > > >
> > > > > ? ? ? ?while (argc-- > 0) {
> > > > > ? ? ? ? ? ? ? ?setcdevname(*argv, NULL, preen);
> > > > > - ? ? ? ? ? ? ? erg = checkfilesys(*argv++);
> > > > > + ? ? ? ? ? ? ? erg = checkfilesys(blockcheck(*argv++));
> > > > > ? ? ? ? ? ? ? ?if (erg > ret)
> > > > > ? ? ? ? ? ? ? ? ? ? ? ?ret = erg;
> > > > > ? ? ? ?}
> > > > 
> > > > $ sudo ./fsck_msdos /dev/rsd6j
> > > > ** /dev/rsd6j
> > > > could not read boot block (Invalid argument)$
> > > 
> > > But what does './fsck_msdos /dev/sd6j' do?
> > 
> > Ah, sorry. Now, it does the same as with raw device.
> > 
> > $ sudo ./fsck_msdos /dev/sd6j
> > ** /dev/rsd6j
> > could not read boot block (Invalid argument)$
> 
> OK, good. :-)
> 
> I am hacking something together to see if it will work. May be a day or
> two. Maybe tonight. :-)
> 
> .... Ken

First very hacky attempt. Could easily destroy your data!

.... Ken


Index: boot.c
===================================================================
RCS file: /cvs/src/sbin/fsck_msdos/boot.c,v
retrieving revision 1.15
diff -u -p -r1.15 boot.c
--- boot.c      18 Dec 2010 04:57:34 -0000      1.15
+++ boot.c      22 Feb 2012 21:12:50 -0000
@@ -33,6 +33,9 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/param.h>
+#include <sys/disklabel.h>
+
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -44,21 +47,43 @@
 int
 readboot(int dosfs, struct bootblock *boot)
 {
-       u_char block[DOSBOOTBLOCKSIZE];
-       u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
+       u_char *block;
+       u_char *fsinfo;
        u_char backup[DOSBOOTBLOCKSIZE];
-       int ret = FSOK;
+       int ret = FSOK, secsize = lab.d_secsize, fsinfosz;
        off_t o;
        ssize_t n;
 
-       if ((n = read(dosfs, block, sizeof block)) == -1 || n != sizeof block) {
+       if (secsize < DOSBOOTBLOCKSIZE) {
+               xperror("sector size < DOSBOOTBLOCKSIZE");
+               return (FSFATAL);
+       }
+       if (DOSBOOTBLOCKSIZE != DEV_BSIZE) {
+               xperror("DOSBOOTBLOCKSIZE != DEV_BSIZE");
+               return (FSFATAL);
+       }
+
+       block = malloc(2 * secsize);
+       if (block == NULL) {
+               xperror("could not malloc boot block");
+               return FSFATAL;
+       }
+
+       if ((o = lseek(dosfs, 0, SEEK_SET)) == -1) {
+               xperror("could not seek boot block");
+               return FSFATAL;
+       }
+
+       n = read(dosfs, block, secsize);
+       if (n == -1 || n != secsize) {
                xperror("could not read boot block");
                return (FSFATAL);
        }
 
        if (block[510] != 0x55 || block[511] != 0xaa) {
-               pfatal("Invalid signature in boot block: %02x%02x\n", 
block[511], block[510]);
-               return FSFATAL;
+               pfatal("Invalid signature in boot block: %02x%02x\n",
+                   block[511], block[510]);
+               return (FSFATAL);
        }
 
        memset(boot, 0, sizeof *boot);
@@ -66,7 +91,15 @@ readboot(int dosfs, struct bootblock *bo
 
        /* decode bios parameter block */
        boot->BytesPerSec = block[11] + (block[12] << 8);
+       if (boot->BytesPerSec == 0 || boot->BytesPerSec != secsize) {
+               pfatal("Invalid sector size: %u\n", boot->BytesPerSec);
+               return (FSFATAL);
+       }
        boot->SecPerClust = block[13];
+       if (boot->SecPerClust == 0) {
+               pfatal("Invalid cluster size: %u\n", boot->SecPerClust);
+               return (FSFATAL);
+       }
        boot->ResSectors = block[14] + (block[15] << 8);
        boot->FATs = block[16];
        boot->RootDirEnts = block[17] + (block[18] << 8);
@@ -100,14 +133,23 @@ readboot(int dosfs, struct bootblock *bo
                boot->FSInfo = block[48] + (block[49] << 8);
                boot->Backup = block[50] + (block[51] << 8);
 
-               o = boot->FSInfo * boot->BytesPerSec;
-               if ((o = lseek(dosfs, o, SEEK_SET)) == -1
-                   || o != boot->FSInfo * boot->BytesPerSec
-                   || (n = read(dosfs, fsinfo, sizeof fsinfo)) == -1
-                   || n != sizeof fsinfo) {
+               o = lseek(dosfs, boot->FSInfo * secsize, SEEK_SET);
+               if (o == -1 || o != boot->FSInfo * secsize) {
+                       xperror("could not seek fsinfo block");
+                       return FSFATAL;
+               }
+
+               if ((2 * DOSBOOTBLOCKSIZE) < secsize)
+                       fsinfosz = secsize;
+               else
+                       fsinfosz = 2 * secsize;
+               n = read(dosfs, block, fsinfosz);
+               if (n == -1 || n != fsinfosz) {
                        xperror("could not read fsinfo block");
                        return FSFATAL;
                }
+               fsinfo = block;
+
                if (memcmp(fsinfo, "RRaA", 4)
                    || memcmp(fsinfo + 0x1e4, "rrAa", 4)
                    || fsinfo[0x1fc]
@@ -129,11 +171,14 @@ readboot(int dosfs, struct bootblock *bo
                                fsinfo[0x3fe] = 0x55;
                                fsinfo[0x3ff] = 0xaa;
 
-                               o = boot->FSInfo * boot->BytesPerSec;
-                               if ((o = lseek(dosfs, o, SEEK_SET)) == -1
-                                   || o != boot->FSInfo * boot->BytesPerSec
-                                   || (n = write(dosfs, fsinfo, sizeof 
fsinfo)) == -1
-                                   || n != sizeof fsinfo) {
+                               o = lseek(dosfs, boot->FSInfo * secsize,
+                                   SEEK_SET);
+                               if (o == -1 || o != boot->FSInfo * secsize) {
+                                       xperror("Unable to seek FSInfo");
+                                       return FSFATAL;
+                               }
+                               n = write(dosfs, block, fsinfosz);
+                               if (n == -1 || n != fsinfosz) {
                                        xperror("Unable to write FSInfo");
                                        return FSFATAL;
                                }
@@ -150,11 +195,13 @@ readboot(int dosfs, struct bootblock *bo
                                       + (fsinfo[0x1ef] << 24);
                }
 
-               o = boot->Backup * boot->BytesPerSec;
-               if ((o = lseek(dosfs, o, SEEK_SET)) == -1
-                   || o != boot->Backup * boot->BytesPerSec
-                   || (n = read(dosfs, backup, sizeof backup)) == -1
-                   || n != sizeof backup) {
+               o = lseek(dosfs, boot->Backup * secsize, SEEK_SET);
+               if (o == -1 || o != boot->Backup * secsize) {
+                       xperror("could not seek backup bootblock");
+                       return (FSFATAL);
+               }
+               n = read(dosfs, block, secsize);
+               if (n == -1 || n != secsize) {
                        xperror("could not read backup bootblock");
                        return FSFATAL;
                }
@@ -181,18 +228,8 @@ readboot(int dosfs, struct bootblock *bo
                /* Check backup FSInfo?                                 XXX */
        }
 
-       if (boot->BytesPerSec == 0 || boot->BytesPerSec % DOSBOOTBLOCKSIZE
-           != 0) {
-               pfatal("Invalid sector size: %u\n", boot->BytesPerSec);
-               return (FSFATAL);
-       }
-       if (boot->SecPerClust == 0) {
-               pfatal("Invalid cluster size: %u\n", boot->SecPerClust);
-               return (FSFATAL);
-       }
-
-       boot->ClusterOffset = (boot->RootDirEnts * 32 + boot->BytesPerSec - 1)
-           / boot->BytesPerSec
+       boot->ClusterOffset = (boot->RootDirEnts * 32 + secsize - 1)
+           / secsize
            + boot->ResSectors
            + boot->FATs * boot->FATsecs
            - CLUST_FIRST * boot->SecPerClust;
@@ -218,13 +255,13 @@ readboot(int dosfs, struct bootblock *bo
 
        switch (boot->ClustMask) {
        case CLUST32_MASK:
-               boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec) / 4;
+               boot->NumFatEntries = (boot->FATsecs * secsize) / 4;
                break;
        case CLUST16_MASK:
-               boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec) / 2;
+               boot->NumFatEntries = (boot->FATsecs * secsize) / 2;
                break;
        default:
-               boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec * 2) / 
3;
+               boot->NumFatEntries = (boot->FATsecs * secsize * 2) / 3;
                break;
        }
 
@@ -233,7 +270,7 @@ readboot(int dosfs, struct bootblock *bo
                       boot->NumClusters, boot->FATsecs);
                return (FSFATAL);
        }
-       boot->ClusterSize = boot->BytesPerSec * boot->SecPerClust;
+       boot->ClusterSize = boot->SecPerClust * secsize;
 
        boot->NumFiles = 1;
        boot->NumFree = 0;
@@ -244,18 +281,34 @@ readboot(int dosfs, struct bootblock *bo
 int
 writefsinfo(int dosfs, struct bootblock *boot)
 {
-       u_char fsinfo[2 * DOSBOOTBLOCKSIZE];
+       u_char *fsinfo;
+       int secsize = lab.d_secsize, fsinfosz;
        off_t o;
        ssize_t n;
 
-       o = boot->FSInfo * boot->BytesPerSec;
-       if ((o = lseek(dosfs, o, SEEK_SET)) == -1
-          || o != boot->FSInfo * boot->BytesPerSec
-          || (n = read(dosfs, fsinfo, sizeof fsinfo)) == -1
-          || n != sizeof fsinfo) {
+       if ((2 * DOSBOOTBLOCKSIZE) < secsize)
+               fsinfosz = secsize;
+       else
+               fsinfosz = 2 * secsize;
+
+       fsinfo = malloc(fsinfosz);
+       if (fsinfo == NULL) {
+               xperror("could not malloc fsinfo block");
+               return FSFATAL;
+       }
+
+       o = lseek(dosfs, boot->FSInfo * secsize, SEEK_SET);
+       if (o == -1 || o != boot->FSInfo * secsize) {
+               xperror("could not seek fsinfo block");
+               return FSFATAL;
+       }
+
+       n = read(dosfs, fsinfo, fsinfosz);
+       if (n == -1 || n != fsinfosz) {
                xperror("could not read fsinfo block");
                return FSFATAL;
        }
+
        fsinfo[0x1e8] = (u_char)boot->FSFree;
        fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8);
        fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16);
@@ -265,14 +318,17 @@ writefsinfo(int dosfs, struct bootblock 
        fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16);
        fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24);
 
-       o = boot->FSInfo * boot->BytesPerSec;
-       if ((o = lseek(dosfs, o, SEEK_SET)) == -1
-           || o != boot->FSInfo * boot->BytesPerSec
-           || (n = write(dosfs, fsinfo, sizeof fsinfo)) == -1
-           || n != sizeof fsinfo) {
+       o = lseek(dosfs, o, SEEK_SET);
+       if (o == -1 || o != boot->FSInfo * boot->BytesPerSec) {
+               xperror("Unable to seek FSInfo");
+               return FSFATAL;
+       }
+       n = write(dosfs, fsinfo, fsinfosz);
+       if (n == -1 || n != fsinfosz) {
                xperror("Unable to write FSInfo");
                return FSFATAL;
        }
+
        /*
         * Technically, we should return FSBOOTMOD here.
         *
Index: check.c
===================================================================
RCS file: /cvs/src/sbin/fsck_msdos/check.c,v
retrieving revision 1.14
diff -u -p -r1.14 check.c
--- check.c     17 Dec 2010 19:36:03 -0000      1.14
+++ check.c     22 Feb 2012 21:12:50 -0000
@@ -34,6 +34,9 @@
  */
 
 #include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/dkio.h>
+#include <sys/disklabel.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -44,6 +47,8 @@
 
 #include "ext.h"
 
+struct disklabel lab;
+
 int
 checkfilesys(const char *fname)
 {
@@ -74,6 +79,9 @@ checkfilesys(const char *fname)
                        printf(" (NO WRITE)");
                printf("\n");
        }
+
+       if (ioctl(dosfs, DIOCGDINFO, (char *)&lab) < 0)
+               pfatal("can't read disk label for %s\n", fname);
 
        if (readboot(dosfs, &boot) != FSOK) {
                (void)close(dosfs);
Index: ext.h
===================================================================
RCS file: /cvs/src/sbin/fsck_msdos/ext.h,v
retrieving revision 1.9
diff -u -p -r1.9 ext.h
--- ext.h       7 Feb 2008 01:34:12 -0000       1.9
+++ ext.h       22 Feb 2012 21:12:50 -0000
@@ -51,7 +51,7 @@ extern int alwaysyes; /* assume "yes" fo
 extern int preen;      /* we are preening */
 extern int rdonly;     /* device is opened read only (supersedes above) */
 
-extern char *fname;    /* filesystem currently checked */
+extern struct disklabel lab;
 
 extern struct dosDirEntry *rootDir;
 
Index: main.c
===================================================================
RCS file: /cvs/src/sbin/fsck_msdos/main.c,v
retrieving revision 1.17
diff -u -p -r1.17 main.c
--- main.c      12 Aug 2010 15:26:34 -0000      1.17
+++ main.c      22 Feb 2012 21:12:50 -0000
@@ -98,7 +98,7 @@ main(int argc, char *argv[])
 
        while (argc-- > 0) {
                setcdevname(*argv, NULL, preen);
-               erg = checkfilesys(*argv++);
+               erg = checkfilesys(blockcheck(*argv++));
                if (erg > ret)
                        ret = erg;
        }

Reply via email to