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