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