1*237d1b14SEd Maste 2*237d1b14SEd Maste /*- 3*237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 4*237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 5*237d1b14SEd Maste * All rights reserved. 6*237d1b14SEd Maste * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 7*237d1b14SEd Maste * 8*237d1b14SEd Maste * Redistribution and use in source and binary forms, with or without 9*237d1b14SEd Maste * modification, are permitted provided that the following conditions 10*237d1b14SEd Maste * are met: 11*237d1b14SEd Maste * 1. Redistributions of source code must retain the above copyright 12*237d1b14SEd Maste * notice, this list of conditions and the following disclaimer. 13*237d1b14SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 14*237d1b14SEd Maste * notice, this list of conditions and the following disclaimer in the 15*237d1b14SEd Maste * documentation and/or other materials provided with the distribution. 16*237d1b14SEd Maste * 3. All advertising materials mentioning features or use of this software 17*237d1b14SEd Maste * must display the following acknowledgement: 18*237d1b14SEd Maste * This product includes software developed by TooLs GmbH. 19*237d1b14SEd Maste * 4. The name of TooLs GmbH may not be used to endorse or promote products 20*237d1b14SEd Maste * derived from this software without specific prior written permission. 21*237d1b14SEd Maste * 22*237d1b14SEd Maste * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23*237d1b14SEd Maste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24*237d1b14SEd Maste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25*237d1b14SEd Maste * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*237d1b14SEd Maste * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27*237d1b14SEd Maste * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28*237d1b14SEd Maste * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29*237d1b14SEd Maste * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30*237d1b14SEd Maste * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31*237d1b14SEd Maste * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*237d1b14SEd Maste */ 33*237d1b14SEd Maste /* 34*237d1b14SEd Maste * Written by Paul Popelka (paulp@uts.amdahl.com) 35*237d1b14SEd Maste * 36*237d1b14SEd Maste * You can do anything you want with this software, just don't say you wrote 37*237d1b14SEd Maste * it, and don't remove this notice. 38*237d1b14SEd Maste * 39*237d1b14SEd Maste * This software is provided "as is". 40*237d1b14SEd Maste * 41*237d1b14SEd Maste * The author supplies this software to be publicly redistributed on the 42*237d1b14SEd Maste * understanding that the author is not responsible for the correct 43*237d1b14SEd Maste * functioning of this software in any circumstances and is not liable for 44*237d1b14SEd Maste * any damages caused by this software. 45*237d1b14SEd Maste * 46*237d1b14SEd Maste * October 1992 47*237d1b14SEd Maste */ 48*237d1b14SEd Maste 49*237d1b14SEd Maste #if HAVE_NBTOOL_CONFIG_H 50*237d1b14SEd Maste #include "nbtool_config.h" 51*237d1b14SEd Maste #endif 52*237d1b14SEd Maste 53*237d1b14SEd Maste #include <sys/cdefs.h> 54*237d1b14SEd Maste /* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */ 55*237d1b14SEd Maste __FBSDID("$FreeBSD$"); 56*237d1b14SEd Maste 57*237d1b14SEd Maste #include <sys/param.h> 58*237d1b14SEd Maste 59*237d1b14SEd Maste #include <ffs/buf.h> 60*237d1b14SEd Maste 61*237d1b14SEd Maste #include <fs/msdosfs/bpb.h> 62*237d1b14SEd Maste #include <fs/msdosfs/bootsect.h> 63*237d1b14SEd Maste #include <fs/msdosfs/direntry.h> 64*237d1b14SEd Maste #include <fs/msdosfs/denode.h> 65*237d1b14SEd Maste #include <fs/msdosfs/msdosfsmount.h> 66*237d1b14SEd Maste #include <fs/msdosfs/fat.h> 67*237d1b14SEd Maste 68*237d1b14SEd Maste #include <stdio.h> 69*237d1b14SEd Maste #include <errno.h> 70*237d1b14SEd Maste #include <stdlib.h> 71*237d1b14SEd Maste #include <string.h> 72*237d1b14SEd Maste #include <util.h> 73*237d1b14SEd Maste 74*237d1b14SEd Maste #include "makefs.h" 75*237d1b14SEd Maste #include "msdos.h" 76*237d1b14SEd Maste #include "mkfs_msdos.h" 77*237d1b14SEd Maste 78*237d1b14SEd Maste #ifdef MSDOSFS_DEBUG 79*237d1b14SEd Maste #define DPRINTF(a) printf a 80*237d1b14SEd Maste #else 81*237d1b14SEd Maste #define DPRINTF(a) 82*237d1b14SEd Maste #endif 83*237d1b14SEd Maste 84*237d1b14SEd Maste struct msdosfsmount * 85*237d1b14SEd Maste msdosfs_mount(struct vnode *devvp, int flags) 86*237d1b14SEd Maste { 87*237d1b14SEd Maste struct msdosfsmount *pmp = NULL; 88*237d1b14SEd Maste struct buf *bp; 89*237d1b14SEd Maste union bootsector *bsp; 90*237d1b14SEd Maste struct byte_bpb33 *b33; 91*237d1b14SEd Maste struct byte_bpb50 *b50; 92*237d1b14SEd Maste struct byte_bpb710 *b710; 93*237d1b14SEd Maste uint8_t SecPerClust; 94*237d1b14SEd Maste int ronly = 0, error, tmp; 95*237d1b14SEd Maste int bsize; 96*237d1b14SEd Maste struct msdos_options *m = devvp->fs->fs_specific; 97*237d1b14SEd Maste uint64_t psize = m->create_size; 98*237d1b14SEd Maste unsigned secsize = 512; 99*237d1b14SEd Maste 100*237d1b14SEd Maste DPRINTF(("%s(bread 0)\n", __func__)); 101*237d1b14SEd Maste if ((error = bread(devvp, 0, secsize, 0, &bp)) != 0) 102*237d1b14SEd Maste goto error_exit; 103*237d1b14SEd Maste 104*237d1b14SEd Maste bsp = (union bootsector *)bp->b_data; 105*237d1b14SEd Maste b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; 106*237d1b14SEd Maste b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; 107*237d1b14SEd Maste b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; 108*237d1b14SEd Maste 109*237d1b14SEd Maste if (!(flags & MSDOSFSMNT_GEMDOSFS)) { 110*237d1b14SEd Maste if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 111*237d1b14SEd Maste || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { 112*237d1b14SEd Maste DPRINTF(("bootsig0 %d bootsig1 %d\n", 113*237d1b14SEd Maste bsp->bs50.bsBootSectSig0, 114*237d1b14SEd Maste bsp->bs50.bsBootSectSig1)); 115*237d1b14SEd Maste error = EINVAL; 116*237d1b14SEd Maste goto error_exit; 117*237d1b14SEd Maste } 118*237d1b14SEd Maste bsize = 0; 119*237d1b14SEd Maste } else 120*237d1b14SEd Maste bsize = 512; 121*237d1b14SEd Maste 122*237d1b14SEd Maste pmp = ecalloc(1, sizeof *pmp); 123*237d1b14SEd Maste /* 124*237d1b14SEd Maste * Compute several useful quantities from the bpb in the 125*237d1b14SEd Maste * bootsector. Copy in the dos 5 variant of the bpb then fix up 126*237d1b14SEd Maste * the fields that are different between dos 5 and dos 3.3. 127*237d1b14SEd Maste */ 128*237d1b14SEd Maste SecPerClust = b50->bpbSecPerClust; 129*237d1b14SEd Maste pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); 130*237d1b14SEd Maste pmp->pm_ResSectors = getushort(b50->bpbResSectors); 131*237d1b14SEd Maste pmp->pm_FATs = b50->bpbFATs; 132*237d1b14SEd Maste pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); 133*237d1b14SEd Maste pmp->pm_Sectors = getushort(b50->bpbSectors); 134*237d1b14SEd Maste pmp->pm_FATsecs = getushort(b50->bpbFATsecs); 135*237d1b14SEd Maste pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); 136*237d1b14SEd Maste pmp->pm_Heads = getushort(b50->bpbHeads); 137*237d1b14SEd Maste pmp->pm_Media = b50->bpbMedia; 138*237d1b14SEd Maste 139*237d1b14SEd Maste DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, RootDirEnts=%u, " 140*237d1b14SEd Maste "Sectors=%u, FATsecs=%lu, SecPerTrack=%u, Heads=%u, Media=%u)\n", 141*237d1b14SEd Maste __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, pmp->pm_FATs, 142*237d1b14SEd Maste pmp->pm_RootDirEnts, pmp->pm_Sectors, pmp->pm_FATsecs, 143*237d1b14SEd Maste pmp->pm_SecPerTrack, pmp->pm_Heads, pmp->pm_Media)); 144*237d1b14SEd Maste if (!(flags & MSDOSFSMNT_GEMDOSFS)) { 145*237d1b14SEd Maste /* XXX - We should probably check more values here */ 146*237d1b14SEd Maste if (!pmp->pm_BytesPerSec || !SecPerClust 147*237d1b14SEd Maste || pmp->pm_SecPerTrack > 63) { 148*237d1b14SEd Maste DPRINTF(("bytespersec %d secperclust %d " 149*237d1b14SEd Maste "secpertrack %d\n", 150*237d1b14SEd Maste pmp->pm_BytesPerSec, SecPerClust, 151*237d1b14SEd Maste pmp->pm_SecPerTrack)); 152*237d1b14SEd Maste error = EINVAL; 153*237d1b14SEd Maste goto error_exit; 154*237d1b14SEd Maste } 155*237d1b14SEd Maste } 156*237d1b14SEd Maste 157*237d1b14SEd Maste pmp->pm_flags = flags & MSDOSFSMNT_MNTOPT; 158*237d1b14SEd Maste if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS) 159*237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_NOWIN95; 160*237d1b14SEd Maste if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) 161*237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; 162*237d1b14SEd Maste 163*237d1b14SEd Maste if (pmp->pm_Sectors == 0) { 164*237d1b14SEd Maste pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); 165*237d1b14SEd Maste pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); 166*237d1b14SEd Maste } else { 167*237d1b14SEd Maste pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); 168*237d1b14SEd Maste pmp->pm_HugeSectors = pmp->pm_Sectors; 169*237d1b14SEd Maste } 170*237d1b14SEd Maste 171*237d1b14SEd Maste if (pmp->pm_RootDirEnts == 0) { 172*237d1b14SEd Maste unsigned short vers = getushort(b710->bpbFSVers); 173*237d1b14SEd Maste /* 174*237d1b14SEd Maste * Some say that bsBootSectSig[23] must be zero, but 175*237d1b14SEd Maste * Windows does not require this and some digital cameras 176*237d1b14SEd Maste * do not set these to zero. Therefore, do not insist. 177*237d1b14SEd Maste */ 178*237d1b14SEd Maste if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) { 179*237d1b14SEd Maste DPRINTF(("sectors %d fatsecs %lu vers %d\n", 180*237d1b14SEd Maste pmp->pm_Sectors, pmp->pm_FATsecs, vers)); 181*237d1b14SEd Maste error = EINVAL; 182*237d1b14SEd Maste goto error_exit; 183*237d1b14SEd Maste } 184*237d1b14SEd Maste pmp->pm_fatmask = FAT32_MASK; 185*237d1b14SEd Maste pmp->pm_fatmult = 4; 186*237d1b14SEd Maste pmp->pm_fatdiv = 1; 187*237d1b14SEd Maste pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); 188*237d1b14SEd Maste 189*237d1b14SEd Maste /* mirrorring is enabled if the FATMIRROR bit is not set */ 190*237d1b14SEd Maste if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0) 191*237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 192*237d1b14SEd Maste else 193*237d1b14SEd Maste pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; 194*237d1b14SEd Maste } else 195*237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 196*237d1b14SEd Maste 197*237d1b14SEd Maste if (flags & MSDOSFSMNT_GEMDOSFS) { 198*237d1b14SEd Maste if (FAT32(pmp)) { 199*237d1b14SEd Maste DPRINTF(("FAT32 for GEMDOS\n")); 200*237d1b14SEd Maste /* 201*237d1b14SEd Maste * GEMDOS doesn't know FAT32. 202*237d1b14SEd Maste */ 203*237d1b14SEd Maste error = EINVAL; 204*237d1b14SEd Maste goto error_exit; 205*237d1b14SEd Maste } 206*237d1b14SEd Maste 207*237d1b14SEd Maste /* 208*237d1b14SEd Maste * Check a few values (could do some more): 209*237d1b14SEd Maste * - logical sector size: power of 2, >= block size 210*237d1b14SEd Maste * - sectors per cluster: power of 2, >= 1 211*237d1b14SEd Maste * - number of sectors: >= 1, <= size of partition 212*237d1b14SEd Maste */ 213*237d1b14SEd Maste if ( (SecPerClust == 0) 214*237d1b14SEd Maste || (SecPerClust & (SecPerClust - 1)) 215*237d1b14SEd Maste || (pmp->pm_BytesPerSec < bsize) 216*237d1b14SEd Maste || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) 217*237d1b14SEd Maste || (pmp->pm_HugeSectors == 0) 218*237d1b14SEd Maste || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize) 219*237d1b14SEd Maste > psize)) { 220*237d1b14SEd Maste DPRINTF(("consistency checks for GEMDOS\n")); 221*237d1b14SEd Maste error = EINVAL; 222*237d1b14SEd Maste goto error_exit; 223*237d1b14SEd Maste } 224*237d1b14SEd Maste /* 225*237d1b14SEd Maste * XXX - Many parts of the msdosfs driver seem to assume that 226*237d1b14SEd Maste * the number of bytes per logical sector (BytesPerSec) will 227*237d1b14SEd Maste * always be the same as the number of bytes per disk block 228*237d1b14SEd Maste * Let's pretend it is. 229*237d1b14SEd Maste */ 230*237d1b14SEd Maste tmp = pmp->pm_BytesPerSec / bsize; 231*237d1b14SEd Maste pmp->pm_BytesPerSec = bsize; 232*237d1b14SEd Maste pmp->pm_HugeSectors *= tmp; 233*237d1b14SEd Maste pmp->pm_HiddenSects *= tmp; 234*237d1b14SEd Maste pmp->pm_ResSectors *= tmp; 235*237d1b14SEd Maste pmp->pm_Sectors *= tmp; 236*237d1b14SEd Maste pmp->pm_FATsecs *= tmp; 237*237d1b14SEd Maste SecPerClust *= tmp; 238*237d1b14SEd Maste } 239*237d1b14SEd Maste 240*237d1b14SEd Maste /* Check that fs has nonzero FAT size */ 241*237d1b14SEd Maste if (pmp->pm_FATsecs == 0) { 242*237d1b14SEd Maste DPRINTF(("FATsecs is 0\n")); 243*237d1b14SEd Maste error = EINVAL; 244*237d1b14SEd Maste goto error_exit; 245*237d1b14SEd Maste } 246*237d1b14SEd Maste 247*237d1b14SEd Maste pmp->pm_fatblk = pmp->pm_ResSectors; 248*237d1b14SEd Maste if (FAT32(pmp)) { 249*237d1b14SEd Maste pmp->pm_rootdirblk = getulong(b710->bpbRootClust); 250*237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_fatblk 251*237d1b14SEd Maste + (pmp->pm_FATs * pmp->pm_FATsecs); 252*237d1b14SEd Maste pmp->pm_fsinfo = getushort(b710->bpbFSInfo); 253*237d1b14SEd Maste } else { 254*237d1b14SEd Maste pmp->pm_rootdirblk = pmp->pm_fatblk + 255*237d1b14SEd Maste (pmp->pm_FATs * pmp->pm_FATsecs); 256*237d1b14SEd Maste pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) 257*237d1b14SEd Maste + pmp->pm_BytesPerSec - 1) 258*237d1b14SEd Maste / pmp->pm_BytesPerSec;/* in sectors */ 259*237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; 260*237d1b14SEd Maste } 261*237d1b14SEd Maste 262*237d1b14SEd Maste pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / 263*237d1b14SEd Maste SecPerClust; 264*237d1b14SEd Maste pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; 265*237d1b14SEd Maste pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; 266*237d1b14SEd Maste 267*237d1b14SEd Maste if (flags & MSDOSFSMNT_GEMDOSFS) { 268*237d1b14SEd Maste if (pmp->pm_nmbrofclusters <= (0xff0 - 2)) { 269*237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 270*237d1b14SEd Maste pmp->pm_fatmult = 3; 271*237d1b14SEd Maste pmp->pm_fatdiv = 2; 272*237d1b14SEd Maste } else { 273*237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 274*237d1b14SEd Maste pmp->pm_fatmult = 2; 275*237d1b14SEd Maste pmp->pm_fatdiv = 1; 276*237d1b14SEd Maste } 277*237d1b14SEd Maste } else if (pmp->pm_fatmask == 0) { 278*237d1b14SEd Maste if (pmp->pm_maxcluster 279*237d1b14SEd Maste <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { 280*237d1b14SEd Maste /* 281*237d1b14SEd Maste * This will usually be a floppy disk. This size makes 282*237d1b14SEd Maste * sure that one FAT entry will not be split across 283*237d1b14SEd Maste * multiple blocks. 284*237d1b14SEd Maste */ 285*237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 286*237d1b14SEd Maste pmp->pm_fatmult = 3; 287*237d1b14SEd Maste pmp->pm_fatdiv = 2; 288*237d1b14SEd Maste } else { 289*237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 290*237d1b14SEd Maste pmp->pm_fatmult = 2; 291*237d1b14SEd Maste pmp->pm_fatdiv = 1; 292*237d1b14SEd Maste } 293*237d1b14SEd Maste } 294*237d1b14SEd Maste if (FAT12(pmp)) 295*237d1b14SEd Maste pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; 296*237d1b14SEd Maste else 297*237d1b14SEd Maste pmp->pm_fatblocksize = MAXBSIZE; 298*237d1b14SEd Maste 299*237d1b14SEd Maste pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; 300*237d1b14SEd Maste pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; 301*237d1b14SEd Maste 302*237d1b14SEd Maste /* 303*237d1b14SEd Maste * Compute mask and shift value for isolating cluster relative byte 304*237d1b14SEd Maste * offsets and cluster numbers from a file offset. 305*237d1b14SEd Maste */ 306*237d1b14SEd Maste pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec; 307*237d1b14SEd Maste pmp->pm_crbomask = pmp->pm_bpcluster - 1; 308*237d1b14SEd Maste pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; 309*237d1b14SEd Maste 310*237d1b14SEd Maste DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, fatblocksize=%lu, " 311*237d1b14SEd Maste "fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, crbomask=%lu, " 312*237d1b14SEd Maste "cnshift=%lu)\n", 313*237d1b14SEd Maste __func__, pmp->pm_fatmask, pmp->pm_fatmult, pmp->pm_fatdiv, 314*237d1b14SEd Maste pmp->pm_fatblocksize, pmp->pm_fatblocksec, pmp->pm_bnshift, 315*237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_crbomask, pmp->pm_cnshift)); 316*237d1b14SEd Maste /* 317*237d1b14SEd Maste * Check for valid cluster size 318*237d1b14SEd Maste * must be a power of 2 319*237d1b14SEd Maste */ 320*237d1b14SEd Maste if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { 321*237d1b14SEd Maste DPRINTF(("bpcluster %lu cnshift %lu\n", 322*237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_cnshift)); 323*237d1b14SEd Maste error = EINVAL; 324*237d1b14SEd Maste goto error_exit; 325*237d1b14SEd Maste } 326*237d1b14SEd Maste 327*237d1b14SEd Maste /* 328*237d1b14SEd Maste * Release the bootsector buffer. 329*237d1b14SEd Maste */ 330*237d1b14SEd Maste brelse(bp, BC_AGE); 331*237d1b14SEd Maste bp = NULL; 332*237d1b14SEd Maste 333*237d1b14SEd Maste /* 334*237d1b14SEd Maste * Check FSInfo. 335*237d1b14SEd Maste */ 336*237d1b14SEd Maste if (pmp->pm_fsinfo) { 337*237d1b14SEd Maste struct fsinfo *fp; 338*237d1b14SEd Maste 339*237d1b14SEd Maste /* 340*237d1b14SEd Maste * XXX If the fsinfo block is stored on media with 341*237d1b14SEd Maste * 2KB or larger sectors, is the fsinfo structure 342*237d1b14SEd Maste * padded at the end or in the middle? 343*237d1b14SEd Maste */ 344*237d1b14SEd Maste DPRINTF(("%s(bread %lu)\n", __func__, 345*237d1b14SEd Maste (unsigned long)de_bn2kb(pmp, pmp->pm_fsinfo))); 346*237d1b14SEd Maste if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo), 347*237d1b14SEd Maste pmp->pm_BytesPerSec, 0, &bp)) != 0) 348*237d1b14SEd Maste goto error_exit; 349*237d1b14SEd Maste fp = (struct fsinfo *)bp->b_data; 350*237d1b14SEd Maste if (!memcmp(fp->fsisig1, "RRaA", 4) 351*237d1b14SEd Maste && !memcmp(fp->fsisig2, "rrAa", 4) 352*237d1b14SEd Maste && !memcmp(fp->fsisig3, "\0\0\125\252", 4) 353*237d1b14SEd Maste && !memcmp(fp->fsisig4, "\0\0\125\252", 4)) 354*237d1b14SEd Maste pmp->pm_nxtfree = getulong(fp->fsinxtfree); 355*237d1b14SEd Maste else 356*237d1b14SEd Maste pmp->pm_fsinfo = 0; 357*237d1b14SEd Maste brelse(bp, 0); 358*237d1b14SEd Maste bp = NULL; 359*237d1b14SEd Maste } 360*237d1b14SEd Maste 361*237d1b14SEd Maste /* 362*237d1b14SEd Maste * Check and validate (or perhaps invalidate?) the fsinfo structure? 363*237d1b14SEd Maste * XXX 364*237d1b14SEd Maste */ 365*237d1b14SEd Maste if (pmp->pm_fsinfo) { 366*237d1b14SEd Maste if ((pmp->pm_nxtfree == 0xffffffffUL) || 367*237d1b14SEd Maste (pmp->pm_nxtfree > pmp->pm_maxcluster)) 368*237d1b14SEd Maste pmp->pm_fsinfo = 0; 369*237d1b14SEd Maste } 370*237d1b14SEd Maste 371*237d1b14SEd Maste /* 372*237d1b14SEd Maste * Allocate memory for the bitmap of allocated clusters, and then 373*237d1b14SEd Maste * fill it in. 374*237d1b14SEd Maste */ 375*237d1b14SEd Maste pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap), 376*237d1b14SEd Maste ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS)); 377*237d1b14SEd Maste /* 378*237d1b14SEd Maste * fillinusemap() needs pm_devvp. 379*237d1b14SEd Maste */ 380*237d1b14SEd Maste pmp->pm_dev = 0; 381*237d1b14SEd Maste pmp->pm_devvp = devvp; 382*237d1b14SEd Maste 383*237d1b14SEd Maste /* 384*237d1b14SEd Maste * Have the inuse map filled in. 385*237d1b14SEd Maste */ 386*237d1b14SEd Maste if ((error = fillinusemap(pmp)) != 0) { 387*237d1b14SEd Maste DPRINTF(("fillinusemap %d\n", error)); 388*237d1b14SEd Maste goto error_exit; 389*237d1b14SEd Maste } 390*237d1b14SEd Maste 391*237d1b14SEd Maste /* 392*237d1b14SEd Maste * Finish up. 393*237d1b14SEd Maste */ 394*237d1b14SEd Maste if (ronly) 395*237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_RONLY; 396*237d1b14SEd Maste else 397*237d1b14SEd Maste pmp->pm_fmod = 1; 398*237d1b14SEd Maste 399*237d1b14SEd Maste /* 400*237d1b14SEd Maste * If we ever do quotas for DOS filesystems this would be a place 401*237d1b14SEd Maste * to fill in the info in the msdosfsmount structure. You dolt, 402*237d1b14SEd Maste * quotas on dos filesystems make no sense because files have no 403*237d1b14SEd Maste * owners on dos filesystems. of course there is some empty space 404*237d1b14SEd Maste * in the directory entry where we could put uid's and gid's. 405*237d1b14SEd Maste */ 406*237d1b14SEd Maste 407*237d1b14SEd Maste return pmp; 408*237d1b14SEd Maste 409*237d1b14SEd Maste error_exit: 410*237d1b14SEd Maste if (bp) 411*237d1b14SEd Maste brelse(bp, BC_AGE); 412*237d1b14SEd Maste if (pmp) { 413*237d1b14SEd Maste if (pmp->pm_inusemap) 414*237d1b14SEd Maste free(pmp->pm_inusemap); 415*237d1b14SEd Maste free(pmp); 416*237d1b14SEd Maste } 417*237d1b14SEd Maste errno = error; 418*237d1b14SEd Maste return NULL; 419*237d1b14SEd Maste } 420*237d1b14SEd Maste 421*237d1b14SEd Maste int 422*237d1b14SEd Maste msdosfs_root(struct msdosfsmount *pmp, struct vnode *vp) { 423*237d1b14SEd Maste struct denode *ndep; 424*237d1b14SEd Maste int error; 425*237d1b14SEd Maste 426*237d1b14SEd Maste *vp = *pmp->pm_devvp; 427*237d1b14SEd Maste if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0) { 428*237d1b14SEd Maste errno = error; 429*237d1b14SEd Maste return -1; 430*237d1b14SEd Maste } 431*237d1b14SEd Maste vp->v_data = ndep; 432*237d1b14SEd Maste return 0; 433*237d1b14SEd Maste } 434