diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2006-12-16 12:44:06 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2006-12-16 12:44:06 +0000 |
commit | 5319a398801f23368225691f44bf07b096eb5e86 (patch) | |
tree | b860cff86b48bf04c8d915f8eb3cb074042ba73e /sys/msdosfs | |
parent | 474330739d2effcf5f82056b412155be23b391fb (diff) |
Adopt FreeBSD's code for non-DEV_BSIZE formatted MSDOSFS filesystems.
Enables devices (e.g. newer iPods, various other mp3 players) that use
2048 byte sectors.
Inspired by original diffs from weingart@ and Alexey Vatchenk.
ok tom@ pedro@ deraadt@ weingart@ marco@
Diffstat (limited to 'sys/msdosfs')
-rw-r--r-- | sys/msdosfs/msdosfs_fat.c | 8 | ||||
-rw-r--r-- | sys/msdosfs/msdosfs_vfsops.c | 45 | ||||
-rw-r--r-- | sys/msdosfs/msdosfsmount.h | 7 |
3 files changed, 44 insertions, 16 deletions
diff --git a/sys/msdosfs/msdosfs_fat.c b/sys/msdosfs/msdosfs_fat.c index c9127de9d85..325620473ee 100644 --- a/sys/msdosfs/msdosfs_fat.c +++ b/sys/msdosfs/msdosfs_fat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_fat.c,v 1.18 2006/10/03 19:49:06 pedro Exp $ */ +/* $OpenBSD: msdosfs_fat.c,v 1.19 2006/12/16 12:44:05 krw Exp $ */ /* $NetBSD: msdosfs_fat.c,v 1.26 1997/10/17 11:24:02 ws Exp $ */ /*- @@ -104,8 +104,7 @@ fatblock(pmp, ofs, bnp, sizep, bop) uint32_t bn, size; bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec; - size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) - * pmp->pm_BytesPerSec; + size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) * DEV_BSIZE; bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs; if (bnp) @@ -365,7 +364,8 @@ updatefats(pmp, bp, fatbn) + ffs(pmp->pm_inusemap[cn / N_INUSEBITS] ^ (u_int)-1) - 1; } - if (bread(pmp->pm_devvp, pmp->pm_fsinfo, 1024, NOCRED, &bpn) != 0) { + if (bread(pmp->pm_devvp, pmp->pm_fsinfo, fsi_size(pmp), NOCRED, + &bpn) != 0) { /* * Ignore the error, but turn off FSInfo update for the future. */ diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c index e64bbe7ba28..c3442966cc1 100644 --- a/sys/msdosfs/msdosfs_vfsops.c +++ b/sys/msdosfs/msdosfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vfsops.c,v 1.45 2006/12/15 03:04:24 krw Exp $ */ +/* $OpenBSD: msdosfs_vfsops.c,v 1.46 2006/12/16 12:44:05 krw Exp $ */ /* $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $ */ /*- @@ -294,7 +294,7 @@ msdosfs_mountfs(devvp, mp, p, argp) * Read the boot sector of the filesystem, and then check the * boot signature. If not a dos boot sector then error out. */ - if ((error = bread(devvp, 0, 512, NOCRED, &bp)) != 0) + if ((error = bread(devvp, 0, 2048, NOCRED, &bp)) != 0) goto error_exit; bp->b_flags |= B_AGE; bsp = (union bootsector *)bp->b_data; @@ -322,6 +322,9 @@ msdosfs_mountfs(devvp, mp, p, argp) pmp->pm_Heads = getushort(b50->bpbHeads); pmp->pm_Media = b50->bpbMedia; + /* Determine the number of DEV_BSIZE blocks in a MSDOSFS sector */ + pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE; + if (!pmp->pm_BytesPerSec || !SecPerClust || pmp->pm_SecPerTrack > 63) { error = EFTYPE; goto error_exit; @@ -352,25 +355,44 @@ msdosfs_mountfs(devvp, mp, p, argp) } else pmp->pm_flags |= MSDOSFS_FATMIRROR; - pmp->pm_fatblk = pmp->pm_ResSectors; + /* + * More sanity checks: + * MSDOSFS sectors per cluster: >0 && power of 2 + * MSDOSFS sector size: >= DEV_BSIZE && power of 2 + * HUGE sector count: >0 + * FAT sectors: >0 + */ + if ((SecPerClust == 0) || (SecPerClust & (SecPerClust - 1)) || + (pmp->pm_BytesPerSec < DEV_BSIZE) || + (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) || + (pmp->pm_HugeSectors == 0) || (pmp->pm_FATsecs == 0)) { + error = EINVAL; + goto error_exit; + } + + pmp->pm_HugeSectors *= pmp->pm_BlkPerSec; + pmp->pm_HiddenSects *= pmp->pm_BlkPerSec; + pmp->pm_FATsecs *= pmp->pm_BlkPerSec; + pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec; + SecPerClust *= pmp->pm_BlkPerSec; + if (FAT32(pmp)) { pmp->pm_rootdirblk = getulong(b710->bpbRootClust); pmp->pm_firstcluster = pmp->pm_fatblk + (pmp->pm_FATs * pmp->pm_FATsecs); - pmp->pm_fsinfo = getushort(b710->bpbFSInfo); + pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec; } else { pmp->pm_rootdirblk = pmp->pm_fatblk + (pmp->pm_FATs * pmp->pm_FATsecs); pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) - + pmp->pm_BytesPerSec - 1) - / pmp->pm_BytesPerSec;/* in sectors */ + + DEV_BSIZE - 1) / DEV_BSIZE; pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; } pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / SecPerClust; pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; - pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; + pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE; if (pmp->pm_fatmask == 0) { if (pmp->pm_maxcluster @@ -417,14 +439,14 @@ msdosfs_mountfs(devvp, mp, p, argp) pmp->pm_maxcluster = fat_max_clusters - 1; } - pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; - pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; + pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE; + pmp->pm_bnshift = ffs(DEV_BSIZE) - 1; /* * Compute mask and shift value for isolating cluster relative byte * offsets and cluster numbers from a file offset. */ - pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec; + pmp->pm_bpcluster = SecPerClust * DEV_BSIZE; pmp->pm_crbomask = pmp->pm_bpcluster - 1; pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; @@ -449,7 +471,8 @@ msdosfs_mountfs(devvp, mp, p, argp) if (pmp->pm_fsinfo) { struct fsinfo *fp; - if ((error = bread(devvp, pmp->pm_fsinfo, 1024, NOCRED, &bp)) != 0) + if ((error = bread(devvp, pmp->pm_fsinfo, fsi_size(pmp), + NOCRED, &bp)) != 0) goto error_exit; fp = (struct fsinfo *)bp->b_data; if (!bcmp(fp->fsisig1, "RRaA", 4) diff --git a/sys/msdosfs/msdosfsmount.h b/sys/msdosfs/msdosfsmount.h index 56f2cd971ff..45f72016fde 100644 --- a/sys/msdosfs/msdosfsmount.h +++ b/sys/msdosfs/msdosfsmount.h @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfsmount.h,v 1.17 2006/12/15 03:04:24 krw Exp $ */ +/* $OpenBSD: msdosfsmount.h,v 1.18 2006/12/16 12:44:05 krw Exp $ */ /* $NetBSD: msdosfsmount.h,v 1.16 1997/10/17 11:24:24 ws Exp $ */ /*- @@ -59,6 +59,7 @@ struct msdosfsmount { mode_t pm_mask; /* mask to and with file protection bits */ struct vnode *pm_devvp; /* vnode for block device mntd */ struct bpb50 pm_bpb; /* BIOS parameter blk for this fs */ + uint32_t pm_BlkPerSec; /* # of DEV_BSIZE blocks in MSDOSFS sector */ uint32_t pm_FATsecs; /* actual number of fat sectors */ uint32_t pm_fatblk; /* block # of first FAT */ uint32_t pm_rootdirblk; /* block # (cluster # for FAT32) of root directory number */ @@ -195,6 +196,10 @@ struct msdosfsmount { ? roottobn((pmp), (dirofs)) \ : cntobn((pmp), (dirclu))) +/* Calculate size of fsinfo block */ +#define fsi_size(pmp) \ + (1024 << ((pmp)->pm_BlkPerSec >> 2)) + /* * Prototypes for MSDOSFS virtual filesystem operations */ |