1237d1b14SEd Maste /*- 2237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 3237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 4237d1b14SEd Maste * All rights reserved. 5237d1b14SEd Maste * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 6237d1b14SEd Maste * 7237d1b14SEd Maste * Redistribution and use in source and binary forms, with or without 8237d1b14SEd Maste * modification, are permitted provided that the following conditions 9237d1b14SEd Maste * are met: 10237d1b14SEd Maste * 1. Redistributions of source code must retain the above copyright 11237d1b14SEd Maste * notice, this list of conditions and the following disclaimer. 12237d1b14SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 13237d1b14SEd Maste * notice, this list of conditions and the following disclaimer in the 14237d1b14SEd Maste * documentation and/or other materials provided with the distribution. 15237d1b14SEd Maste * 3. All advertising materials mentioning features or use of this software 16237d1b14SEd Maste * must display the following acknowledgement: 17237d1b14SEd Maste * This product includes software developed by TooLs GmbH. 18237d1b14SEd Maste * 4. The name of TooLs GmbH may not be used to endorse or promote products 19237d1b14SEd Maste * derived from this software without specific prior written permission. 20237d1b14SEd Maste * 21237d1b14SEd Maste * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 22237d1b14SEd Maste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23237d1b14SEd Maste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24237d1b14SEd Maste * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25237d1b14SEd Maste * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26237d1b14SEd Maste * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 27237d1b14SEd Maste * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28237d1b14SEd Maste * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 29237d1b14SEd Maste * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 30237d1b14SEd Maste * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31237d1b14SEd Maste */ 32237d1b14SEd Maste /* 33237d1b14SEd Maste * Written by Paul Popelka (paulp@uts.amdahl.com) 34237d1b14SEd Maste * 35237d1b14SEd Maste * You can do anything you want with this software, just don't say you wrote 36237d1b14SEd Maste * it, and don't remove this notice. 37237d1b14SEd Maste * 38237d1b14SEd Maste * This software is provided "as is". 39237d1b14SEd Maste * 40237d1b14SEd Maste * The author supplies this software to be publicly redistributed on the 41237d1b14SEd Maste * understanding that the author is not responsible for the correct 42237d1b14SEd Maste * functioning of this software in any circumstances and is not liable for 43237d1b14SEd Maste * any damages caused by this software. 44237d1b14SEd Maste * 45237d1b14SEd Maste * October 1992 46237d1b14SEd Maste */ 47237d1b14SEd Maste 48237d1b14SEd Maste #if HAVE_NBTOOL_CONFIG_H 49237d1b14SEd Maste #include "nbtool_config.h" 50237d1b14SEd Maste #endif 51237d1b14SEd Maste 52237d1b14SEd Maste #include <sys/cdefs.h> 53237d1b14SEd Maste /* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */ 54237d1b14SEd Maste __FBSDID("$FreeBSD$"); 55237d1b14SEd Maste 56237d1b14SEd Maste #include <sys/param.h> 57237d1b14SEd Maste 58237d1b14SEd Maste #include <ffs/buf.h> 59237d1b14SEd Maste 60237d1b14SEd Maste #include <fs/msdosfs/bpb.h> 61237d1b14SEd Maste #include <fs/msdosfs/bootsect.h> 62237d1b14SEd Maste #include <fs/msdosfs/direntry.h> 63237d1b14SEd Maste #include <fs/msdosfs/denode.h> 64237d1b14SEd Maste #include <fs/msdosfs/msdosfsmount.h> 65237d1b14SEd Maste #include <fs/msdosfs/fat.h> 66237d1b14SEd Maste 67237d1b14SEd Maste #include <stdio.h> 68237d1b14SEd Maste #include <errno.h> 69237d1b14SEd Maste #include <stdlib.h> 70237d1b14SEd Maste #include <string.h> 71237d1b14SEd Maste #include <util.h> 72237d1b14SEd Maste 73237d1b14SEd Maste #include "makefs.h" 74237d1b14SEd Maste #include "msdos.h" 75237d1b14SEd Maste #include "mkfs_msdos.h" 76237d1b14SEd Maste 77237d1b14SEd Maste #ifdef MSDOSFS_DEBUG 78237d1b14SEd Maste #define DPRINTF(a) printf a 79237d1b14SEd Maste #else 80237d1b14SEd Maste #define DPRINTF(a) 81237d1b14SEd Maste #endif 82237d1b14SEd Maste 83237d1b14SEd Maste struct msdosfsmount * 84237d1b14SEd Maste msdosfs_mount(struct vnode *devvp, int flags) 85237d1b14SEd Maste { 86237d1b14SEd Maste struct msdosfsmount *pmp = NULL; 87237d1b14SEd Maste struct buf *bp; 88237d1b14SEd Maste union bootsector *bsp; 89237d1b14SEd Maste struct byte_bpb33 *b33; 90237d1b14SEd Maste struct byte_bpb50 *b50; 91237d1b14SEd Maste struct byte_bpb710 *b710; 92237d1b14SEd Maste uint8_t SecPerClust; 93237d1b14SEd Maste int ronly = 0, error, tmp; 94237d1b14SEd Maste int bsize; 95237d1b14SEd Maste struct msdos_options *m = devvp->fs->fs_specific; 96237d1b14SEd Maste uint64_t psize = m->create_size; 97237d1b14SEd Maste unsigned secsize = 512; 98237d1b14SEd Maste 99237d1b14SEd Maste DPRINTF(("%s(bread 0)\n", __func__)); 100237d1b14SEd Maste if ((error = bread(devvp, 0, secsize, 0, &bp)) != 0) 101237d1b14SEd Maste goto error_exit; 102237d1b14SEd Maste 103237d1b14SEd Maste bsp = (union bootsector *)bp->b_data; 104237d1b14SEd Maste b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; 105237d1b14SEd Maste b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; 106237d1b14SEd Maste b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; 107237d1b14SEd Maste 108237d1b14SEd Maste if (!(flags & MSDOSFSMNT_GEMDOSFS)) { 109237d1b14SEd Maste if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 110237d1b14SEd Maste || bsp->bs50.bsBootSectSig1 != BOOTSIG1) { 111237d1b14SEd Maste DPRINTF(("bootsig0 %d bootsig1 %d\n", 112237d1b14SEd Maste bsp->bs50.bsBootSectSig0, 113237d1b14SEd Maste bsp->bs50.bsBootSectSig1)); 114237d1b14SEd Maste error = EINVAL; 115237d1b14SEd Maste goto error_exit; 116237d1b14SEd Maste } 117237d1b14SEd Maste bsize = 0; 118237d1b14SEd Maste } else 119237d1b14SEd Maste bsize = 512; 120237d1b14SEd Maste 121237d1b14SEd Maste pmp = ecalloc(1, sizeof *pmp); 122237d1b14SEd Maste /* 123237d1b14SEd Maste * Compute several useful quantities from the bpb in the 124237d1b14SEd Maste * bootsector. Copy in the dos 5 variant of the bpb then fix up 125237d1b14SEd Maste * the fields that are different between dos 5 and dos 3.3. 126237d1b14SEd Maste */ 127237d1b14SEd Maste SecPerClust = b50->bpbSecPerClust; 128237d1b14SEd Maste pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); 129237d1b14SEd Maste pmp->pm_ResSectors = getushort(b50->bpbResSectors); 130237d1b14SEd Maste pmp->pm_FATs = b50->bpbFATs; 131237d1b14SEd Maste pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); 132237d1b14SEd Maste pmp->pm_Sectors = getushort(b50->bpbSectors); 133237d1b14SEd Maste pmp->pm_FATsecs = getushort(b50->bpbFATsecs); 134237d1b14SEd Maste pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); 135237d1b14SEd Maste pmp->pm_Heads = getushort(b50->bpbHeads); 136237d1b14SEd Maste pmp->pm_Media = b50->bpbMedia; 137237d1b14SEd Maste 138237d1b14SEd Maste DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, RootDirEnts=%u, " 139237d1b14SEd Maste "Sectors=%u, FATsecs=%lu, SecPerTrack=%u, Heads=%u, Media=%u)\n", 140237d1b14SEd Maste __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, pmp->pm_FATs, 141237d1b14SEd Maste pmp->pm_RootDirEnts, pmp->pm_Sectors, pmp->pm_FATsecs, 142237d1b14SEd Maste pmp->pm_SecPerTrack, pmp->pm_Heads, pmp->pm_Media)); 143237d1b14SEd Maste if (!(flags & MSDOSFSMNT_GEMDOSFS)) { 144237d1b14SEd Maste /* XXX - We should probably check more values here */ 145237d1b14SEd Maste if (!pmp->pm_BytesPerSec || !SecPerClust 146237d1b14SEd Maste || pmp->pm_SecPerTrack > 63) { 147237d1b14SEd Maste DPRINTF(("bytespersec %d secperclust %d " 148237d1b14SEd Maste "secpertrack %d\n", 149237d1b14SEd Maste pmp->pm_BytesPerSec, SecPerClust, 150237d1b14SEd Maste pmp->pm_SecPerTrack)); 151237d1b14SEd Maste error = EINVAL; 152237d1b14SEd Maste goto error_exit; 153237d1b14SEd Maste } 154237d1b14SEd Maste } 155237d1b14SEd Maste 156237d1b14SEd Maste pmp->pm_flags = flags & MSDOSFSMNT_MNTOPT; 157237d1b14SEd Maste if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS) 158237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_NOWIN95; 159237d1b14SEd Maste if (pmp->pm_flags & MSDOSFSMNT_NOWIN95) 160237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_SHORTNAME; 161237d1b14SEd Maste 162237d1b14SEd Maste if (pmp->pm_Sectors == 0) { 163237d1b14SEd Maste pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); 164237d1b14SEd Maste pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); 165237d1b14SEd Maste } else { 166237d1b14SEd Maste pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); 167237d1b14SEd Maste pmp->pm_HugeSectors = pmp->pm_Sectors; 168237d1b14SEd Maste } 169237d1b14SEd Maste 170237d1b14SEd Maste if (pmp->pm_RootDirEnts == 0) { 171237d1b14SEd Maste unsigned short vers = getushort(b710->bpbFSVers); 172237d1b14SEd Maste /* 173237d1b14SEd Maste * Some say that bsBootSectSig[23] must be zero, but 174237d1b14SEd Maste * Windows does not require this and some digital cameras 175237d1b14SEd Maste * do not set these to zero. Therefore, do not insist. 176237d1b14SEd Maste */ 177237d1b14SEd Maste if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) { 178237d1b14SEd Maste DPRINTF(("sectors %d fatsecs %lu vers %d\n", 179237d1b14SEd Maste pmp->pm_Sectors, pmp->pm_FATsecs, vers)); 180237d1b14SEd Maste error = EINVAL; 181237d1b14SEd Maste goto error_exit; 182237d1b14SEd Maste } 183237d1b14SEd Maste pmp->pm_fatmask = FAT32_MASK; 184237d1b14SEd Maste pmp->pm_fatmult = 4; 185237d1b14SEd Maste pmp->pm_fatdiv = 1; 186237d1b14SEd Maste pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); 187237d1b14SEd Maste 188237d1b14SEd Maste /* mirrorring is enabled if the FATMIRROR bit is not set */ 189237d1b14SEd Maste if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0) 190237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 191237d1b14SEd Maste else 192237d1b14SEd Maste pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; 193237d1b14SEd Maste } else 194237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 195237d1b14SEd Maste 196237d1b14SEd Maste if (flags & MSDOSFSMNT_GEMDOSFS) { 197237d1b14SEd Maste if (FAT32(pmp)) { 198237d1b14SEd Maste DPRINTF(("FAT32 for GEMDOS\n")); 199237d1b14SEd Maste /* 200237d1b14SEd Maste * GEMDOS doesn't know FAT32. 201237d1b14SEd Maste */ 202237d1b14SEd Maste error = EINVAL; 203237d1b14SEd Maste goto error_exit; 204237d1b14SEd Maste } 205237d1b14SEd Maste 206237d1b14SEd Maste /* 207237d1b14SEd Maste * Check a few values (could do some more): 208237d1b14SEd Maste * - logical sector size: power of 2, >= block size 209237d1b14SEd Maste * - sectors per cluster: power of 2, >= 1 210237d1b14SEd Maste * - number of sectors: >= 1, <= size of partition 211237d1b14SEd Maste */ 212237d1b14SEd Maste if ( (SecPerClust == 0) 213237d1b14SEd Maste || (SecPerClust & (SecPerClust - 1)) 214237d1b14SEd Maste || (pmp->pm_BytesPerSec < bsize) 215237d1b14SEd Maste || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) 216237d1b14SEd Maste || (pmp->pm_HugeSectors == 0) 217237d1b14SEd Maste || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize) 218237d1b14SEd Maste > psize)) { 219237d1b14SEd Maste DPRINTF(("consistency checks for GEMDOS\n")); 220237d1b14SEd Maste error = EINVAL; 221237d1b14SEd Maste goto error_exit; 222237d1b14SEd Maste } 223237d1b14SEd Maste /* 224237d1b14SEd Maste * XXX - Many parts of the msdosfs driver seem to assume that 225237d1b14SEd Maste * the number of bytes per logical sector (BytesPerSec) will 226237d1b14SEd Maste * always be the same as the number of bytes per disk block 227237d1b14SEd Maste * Let's pretend it is. 228237d1b14SEd Maste */ 229237d1b14SEd Maste tmp = pmp->pm_BytesPerSec / bsize; 230237d1b14SEd Maste pmp->pm_BytesPerSec = bsize; 231237d1b14SEd Maste pmp->pm_HugeSectors *= tmp; 232237d1b14SEd Maste pmp->pm_HiddenSects *= tmp; 233237d1b14SEd Maste pmp->pm_ResSectors *= tmp; 234237d1b14SEd Maste pmp->pm_Sectors *= tmp; 235237d1b14SEd Maste pmp->pm_FATsecs *= tmp; 236237d1b14SEd Maste SecPerClust *= tmp; 237237d1b14SEd Maste } 238237d1b14SEd Maste 239237d1b14SEd Maste /* Check that fs has nonzero FAT size */ 240237d1b14SEd Maste if (pmp->pm_FATsecs == 0) { 241237d1b14SEd Maste DPRINTF(("FATsecs is 0\n")); 242237d1b14SEd Maste error = EINVAL; 243237d1b14SEd Maste goto error_exit; 244237d1b14SEd Maste } 245237d1b14SEd Maste 246237d1b14SEd Maste pmp->pm_fatblk = pmp->pm_ResSectors; 247237d1b14SEd Maste if (FAT32(pmp)) { 248237d1b14SEd Maste pmp->pm_rootdirblk = getulong(b710->bpbRootClust); 249237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_fatblk 250237d1b14SEd Maste + (pmp->pm_FATs * pmp->pm_FATsecs); 251237d1b14SEd Maste pmp->pm_fsinfo = getushort(b710->bpbFSInfo); 252237d1b14SEd Maste } else { 253237d1b14SEd Maste pmp->pm_rootdirblk = pmp->pm_fatblk + 254237d1b14SEd Maste (pmp->pm_FATs * pmp->pm_FATsecs); 255237d1b14SEd Maste pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) 256237d1b14SEd Maste + pmp->pm_BytesPerSec - 1) 257237d1b14SEd Maste / pmp->pm_BytesPerSec;/* in sectors */ 258237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; 259237d1b14SEd Maste } 260237d1b14SEd Maste 261237d1b14SEd Maste pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / 262237d1b14SEd Maste SecPerClust; 263237d1b14SEd Maste pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; 264237d1b14SEd Maste pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; 265237d1b14SEd Maste 266237d1b14SEd Maste if (flags & MSDOSFSMNT_GEMDOSFS) { 267237d1b14SEd Maste if (pmp->pm_nmbrofclusters <= (0xff0 - 2)) { 268237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 269237d1b14SEd Maste pmp->pm_fatmult = 3; 270237d1b14SEd Maste pmp->pm_fatdiv = 2; 271237d1b14SEd Maste } else { 272237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 273237d1b14SEd Maste pmp->pm_fatmult = 2; 274237d1b14SEd Maste pmp->pm_fatdiv = 1; 275237d1b14SEd Maste } 276237d1b14SEd Maste } else if (pmp->pm_fatmask == 0) { 277237d1b14SEd Maste if (pmp->pm_maxcluster 278237d1b14SEd Maste <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { 279237d1b14SEd Maste /* 280237d1b14SEd Maste * This will usually be a floppy disk. This size makes 281237d1b14SEd Maste * sure that one FAT entry will not be split across 282237d1b14SEd Maste * multiple blocks. 283237d1b14SEd Maste */ 284237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 285237d1b14SEd Maste pmp->pm_fatmult = 3; 286237d1b14SEd Maste pmp->pm_fatdiv = 2; 287237d1b14SEd Maste } else { 288237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 289237d1b14SEd Maste pmp->pm_fatmult = 2; 290237d1b14SEd Maste pmp->pm_fatdiv = 1; 291237d1b14SEd Maste } 292237d1b14SEd Maste } 293237d1b14SEd Maste if (FAT12(pmp)) 294237d1b14SEd Maste pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; 295237d1b14SEd Maste else 296237d1b14SEd Maste pmp->pm_fatblocksize = MAXBSIZE; 297237d1b14SEd Maste 298237d1b14SEd Maste pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; 299237d1b14SEd Maste pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; 300237d1b14SEd Maste 301237d1b14SEd Maste /* 302237d1b14SEd Maste * Compute mask and shift value for isolating cluster relative byte 303237d1b14SEd Maste * offsets and cluster numbers from a file offset. 304237d1b14SEd Maste */ 305237d1b14SEd Maste pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec; 306237d1b14SEd Maste pmp->pm_crbomask = pmp->pm_bpcluster - 1; 307237d1b14SEd Maste pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; 308237d1b14SEd Maste 309237d1b14SEd Maste DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, fatblocksize=%lu, " 310237d1b14SEd Maste "fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, crbomask=%lu, " 311237d1b14SEd Maste "cnshift=%lu)\n", 312237d1b14SEd Maste __func__, pmp->pm_fatmask, pmp->pm_fatmult, pmp->pm_fatdiv, 313237d1b14SEd Maste pmp->pm_fatblocksize, pmp->pm_fatblocksec, pmp->pm_bnshift, 314237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_crbomask, pmp->pm_cnshift)); 315237d1b14SEd Maste /* 316237d1b14SEd Maste * Check for valid cluster size 317237d1b14SEd Maste * must be a power of 2 318237d1b14SEd Maste */ 319237d1b14SEd Maste if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { 320237d1b14SEd Maste DPRINTF(("bpcluster %lu cnshift %lu\n", 321237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_cnshift)); 322237d1b14SEd Maste error = EINVAL; 323237d1b14SEd Maste goto error_exit; 324237d1b14SEd Maste } 325237d1b14SEd Maste 326237d1b14SEd Maste /* 327237d1b14SEd Maste * Release the bootsector buffer. 328237d1b14SEd Maste */ 329*5b292f9aSEd Maste brelse(bp); 330237d1b14SEd Maste bp = NULL; 331237d1b14SEd Maste 332237d1b14SEd Maste /* 333237d1b14SEd Maste * Check FSInfo. 334237d1b14SEd Maste */ 335237d1b14SEd Maste if (pmp->pm_fsinfo) { 336237d1b14SEd Maste struct fsinfo *fp; 337237d1b14SEd Maste 338237d1b14SEd Maste /* 339237d1b14SEd Maste * XXX If the fsinfo block is stored on media with 340237d1b14SEd Maste * 2KB or larger sectors, is the fsinfo structure 341237d1b14SEd Maste * padded at the end or in the middle? 342237d1b14SEd Maste */ 343237d1b14SEd Maste DPRINTF(("%s(bread %lu)\n", __func__, 344237d1b14SEd Maste (unsigned long)de_bn2kb(pmp, pmp->pm_fsinfo))); 345237d1b14SEd Maste if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo), 346237d1b14SEd Maste pmp->pm_BytesPerSec, 0, &bp)) != 0) 347237d1b14SEd Maste goto error_exit; 348237d1b14SEd Maste fp = (struct fsinfo *)bp->b_data; 349237d1b14SEd Maste if (!memcmp(fp->fsisig1, "RRaA", 4) 350237d1b14SEd Maste && !memcmp(fp->fsisig2, "rrAa", 4) 351237d1b14SEd Maste && !memcmp(fp->fsisig3, "\0\0\125\252", 4) 352237d1b14SEd Maste && !memcmp(fp->fsisig4, "\0\0\125\252", 4)) 353237d1b14SEd Maste pmp->pm_nxtfree = getulong(fp->fsinxtfree); 354237d1b14SEd Maste else 355237d1b14SEd Maste pmp->pm_fsinfo = 0; 356*5b292f9aSEd Maste brelse(bp); 357237d1b14SEd Maste bp = NULL; 358237d1b14SEd Maste } 359237d1b14SEd Maste 360237d1b14SEd Maste /* 361237d1b14SEd Maste * Check and validate (or perhaps invalidate?) the fsinfo structure? 362237d1b14SEd Maste * XXX 363237d1b14SEd Maste */ 364237d1b14SEd Maste if (pmp->pm_fsinfo) { 365237d1b14SEd Maste if ((pmp->pm_nxtfree == 0xffffffffUL) || 366237d1b14SEd Maste (pmp->pm_nxtfree > pmp->pm_maxcluster)) 367237d1b14SEd Maste pmp->pm_fsinfo = 0; 368237d1b14SEd Maste } 369237d1b14SEd Maste 370237d1b14SEd Maste /* 371237d1b14SEd Maste * Allocate memory for the bitmap of allocated clusters, and then 372237d1b14SEd Maste * fill it in. 373237d1b14SEd Maste */ 374237d1b14SEd Maste pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap), 375237d1b14SEd Maste ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS)); 376237d1b14SEd Maste /* 377237d1b14SEd Maste * fillinusemap() needs pm_devvp. 378237d1b14SEd Maste */ 379237d1b14SEd Maste pmp->pm_dev = 0; 380237d1b14SEd Maste pmp->pm_devvp = devvp; 381237d1b14SEd Maste 382237d1b14SEd Maste /* 383237d1b14SEd Maste * Have the inuse map filled in. 384237d1b14SEd Maste */ 385237d1b14SEd Maste if ((error = fillinusemap(pmp)) != 0) { 386237d1b14SEd Maste DPRINTF(("fillinusemap %d\n", error)); 387237d1b14SEd Maste goto error_exit; 388237d1b14SEd Maste } 389237d1b14SEd Maste 390237d1b14SEd Maste /* 391237d1b14SEd Maste * Finish up. 392237d1b14SEd Maste */ 393237d1b14SEd Maste if (ronly) 394237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_RONLY; 395237d1b14SEd Maste else 396237d1b14SEd Maste pmp->pm_fmod = 1; 397237d1b14SEd Maste 398237d1b14SEd Maste /* 399237d1b14SEd Maste * If we ever do quotas for DOS filesystems this would be a place 400237d1b14SEd Maste * to fill in the info in the msdosfsmount structure. You dolt, 401237d1b14SEd Maste * quotas on dos filesystems make no sense because files have no 402237d1b14SEd Maste * owners on dos filesystems. of course there is some empty space 403237d1b14SEd Maste * in the directory entry where we could put uid's and gid's. 404237d1b14SEd Maste */ 405237d1b14SEd Maste 406237d1b14SEd Maste return pmp; 407237d1b14SEd Maste 408237d1b14SEd Maste error_exit: 409237d1b14SEd Maste if (bp) 410237d1b14SEd Maste brelse(bp, BC_AGE); 411237d1b14SEd Maste if (pmp) { 412237d1b14SEd Maste if (pmp->pm_inusemap) 413237d1b14SEd Maste free(pmp->pm_inusemap); 414237d1b14SEd Maste free(pmp); 415237d1b14SEd Maste } 416237d1b14SEd Maste errno = error; 417237d1b14SEd Maste return NULL; 418237d1b14SEd Maste } 419237d1b14SEd Maste 420237d1b14SEd Maste int 421237d1b14SEd Maste msdosfs_root(struct msdosfsmount *pmp, struct vnode *vp) { 422237d1b14SEd Maste struct denode *ndep; 423237d1b14SEd Maste int error; 424237d1b14SEd Maste 425237d1b14SEd Maste *vp = *pmp->pm_devvp; 426237d1b14SEd Maste if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0) { 427237d1b14SEd Maste errno = error; 428237d1b14SEd Maste return -1; 429237d1b14SEd Maste } 430237d1b14SEd Maste vp->v_data = ndep; 431237d1b14SEd Maste return 0; 432237d1b14SEd Maste } 433