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;
}