1237d1b14SEd Maste /*- 22037e988SEd Maste * SPDX-License-Identifier: BSD-4-Clause 32037e988SEd Maste * 4237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 5237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 6237d1b14SEd Maste * All rights reserved. 7237d1b14SEd Maste * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 8237d1b14SEd Maste * 9237d1b14SEd Maste * Redistribution and use in source and binary forms, with or without 10237d1b14SEd Maste * modification, are permitted provided that the following conditions 11237d1b14SEd Maste * are met: 12237d1b14SEd Maste * 1. Redistributions of source code must retain the above copyright 13237d1b14SEd Maste * notice, this list of conditions and the following disclaimer. 14237d1b14SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 15237d1b14SEd Maste * notice, this list of conditions and the following disclaimer in the 16237d1b14SEd Maste * documentation and/or other materials provided with the distribution. 17237d1b14SEd Maste * 3. All advertising materials mentioning features or use of this software 18237d1b14SEd Maste * must display the following acknowledgement: 19237d1b14SEd Maste * This product includes software developed by TooLs GmbH. 20237d1b14SEd Maste * 4. The name of TooLs GmbH may not be used to endorse or promote products 21237d1b14SEd Maste * derived from this software without specific prior written permission. 22237d1b14SEd Maste * 23237d1b14SEd Maste * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24237d1b14SEd Maste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25237d1b14SEd Maste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26237d1b14SEd Maste * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27237d1b14SEd Maste * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28237d1b14SEd Maste * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29237d1b14SEd Maste * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30237d1b14SEd Maste * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31237d1b14SEd Maste * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32237d1b14SEd Maste * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33237d1b14SEd Maste */ 342037e988SEd Maste /*- 35237d1b14SEd Maste * Written by Paul Popelka (paulp@uts.amdahl.com) 36237d1b14SEd Maste * 37237d1b14SEd Maste * You can do anything you want with this software, just don't say you wrote 38237d1b14SEd Maste * it, and don't remove this notice. 39237d1b14SEd Maste * 40237d1b14SEd Maste * This software is provided "as is". 41237d1b14SEd Maste * 42237d1b14SEd Maste * The author supplies this software to be publicly redistributed on the 43237d1b14SEd Maste * understanding that the author is not responsible for the correct 44237d1b14SEd Maste * functioning of this software in any circumstances and is not liable for 45237d1b14SEd Maste * any damages caused by this software. 46237d1b14SEd Maste * 47237d1b14SEd Maste * October 1992 48237d1b14SEd Maste */ 49237d1b14SEd Maste 50237d1b14SEd Maste #include <sys/cdefs.h> 51237d1b14SEd Maste /* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */ 52237d1b14SEd Maste __FBSDID("$FreeBSD$"); 53237d1b14SEd Maste 54237d1b14SEd Maste #include <sys/param.h> 5598dc8da5SEd Maste #include <sys/mount.h> 56237d1b14SEd Maste 57237d1b14SEd Maste #include <errno.h> 5898dc8da5SEd Maste #include <stdio.h> 59237d1b14SEd Maste #include <string.h> 6098dc8da5SEd Maste #include <stdlib.h> 61237d1b14SEd Maste #include <util.h> 62237d1b14SEd Maste 63476b0ab7SEd Maste #include "ffs/buf.h" 6498dc8da5SEd Maste #include <fs/msdosfs/bootsect.h> 6598dc8da5SEd Maste #include <fs/msdosfs/bpb.h> 66476b0ab7SEd Maste #include "msdos/direntry.h" 67476b0ab7SEd Maste #include <fs/msdosfs/denode.h> 6851e79affSEd Maste #include <fs/msdosfs/fat.h> 69840aca28SEd Maste #include <fs/msdosfs/msdosfsmount.h> 7098dc8da5SEd Maste 7198dc8da5SEd Maste #include <mkfs_msdos.h> 7298dc8da5SEd Maste 73237d1b14SEd Maste #include "makefs.h" 74237d1b14SEd Maste #include "msdos.h" 75237d1b14SEd Maste 7698dc8da5SEd Maste 77237d1b14SEd Maste 78237d1b14SEd Maste struct msdosfsmount * 7998dc8da5SEd Maste msdosfs_mount(struct vnode *devvp) 80237d1b14SEd Maste { 81237d1b14SEd Maste struct msdosfsmount *pmp = NULL; 82237d1b14SEd Maste struct buf *bp; 83237d1b14SEd Maste union bootsector *bsp; 84237d1b14SEd Maste struct byte_bpb33 *b33; 85237d1b14SEd Maste struct byte_bpb50 *b50; 86237d1b14SEd Maste struct byte_bpb710 *b710; 87237d1b14SEd Maste uint8_t SecPerClust; 8898dc8da5SEd Maste int ronly = 0, error; 89237d1b14SEd Maste int bsize; 90237d1b14SEd Maste unsigned secsize = 512; 91237d1b14SEd Maste 9298dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(bread 0)\n", __func__)); 93237d1b14SEd Maste if ((error = bread(devvp, 0, secsize, 0, &bp)) != 0) 94237d1b14SEd Maste goto error_exit; 95237d1b14SEd Maste 96237d1b14SEd Maste bsp = (union bootsector *)bp->b_data; 97237d1b14SEd Maste b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; 98237d1b14SEd Maste b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; 99237d1b14SEd Maste b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; 100237d1b14SEd Maste 10198dc8da5SEd Maste if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 || 10298dc8da5SEd Maste bsp->bs50.bsBootSectSig1 != BOOTSIG1) { 10398dc8da5SEd Maste MSDOSFS_DPRINTF(("bootsig0 %d bootsig1 %d\n", 104237d1b14SEd Maste bsp->bs50.bsBootSectSig0, 105237d1b14SEd Maste bsp->bs50.bsBootSectSig1)); 106237d1b14SEd Maste error = EINVAL; 107237d1b14SEd Maste goto error_exit; 108237d1b14SEd Maste } 109237d1b14SEd Maste bsize = 0; 110237d1b14SEd Maste 11198dc8da5SEd Maste pmp = ecalloc(1, sizeof(*pmp)); 112237d1b14SEd Maste /* 113237d1b14SEd Maste * Compute several useful quantities from the bpb in the 114237d1b14SEd Maste * bootsector. Copy in the dos 5 variant of the bpb then fix up 115237d1b14SEd Maste * the fields that are different between dos 5 and dos 3.3. 116237d1b14SEd Maste */ 117237d1b14SEd Maste SecPerClust = b50->bpbSecPerClust; 118237d1b14SEd Maste pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); 119237d1b14SEd Maste pmp->pm_ResSectors = getushort(b50->bpbResSectors); 120237d1b14SEd Maste pmp->pm_FATs = b50->bpbFATs; 121237d1b14SEd Maste pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); 122237d1b14SEd Maste pmp->pm_Sectors = getushort(b50->bpbSectors); 123237d1b14SEd Maste pmp->pm_FATsecs = getushort(b50->bpbFATsecs); 124237d1b14SEd Maste pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); 125237d1b14SEd Maste pmp->pm_Heads = getushort(b50->bpbHeads); 126237d1b14SEd Maste pmp->pm_Media = b50->bpbMedia; 127237d1b14SEd Maste 12898dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, " 12998dc8da5SEd Maste "RootDirEnts=%u, Sectors=%u, FATsecs=%lu, SecPerTrack=%u, " 13098dc8da5SEd Maste "Heads=%u, Media=%u)\n", 13198dc8da5SEd Maste __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, 13298dc8da5SEd Maste pmp->pm_FATs, pmp->pm_RootDirEnts, pmp->pm_Sectors, 13398dc8da5SEd Maste pmp->pm_FATsecs, pmp->pm_SecPerTrack, pmp->pm_Heads, 13498dc8da5SEd Maste pmp->pm_Media)); 13598dc8da5SEd Maste 136237d1b14SEd Maste /* XXX - We should probably check more values here */ 137237d1b14SEd Maste if (!pmp->pm_BytesPerSec || !SecPerClust 138237d1b14SEd Maste || pmp->pm_SecPerTrack > 63) { 13998dc8da5SEd Maste MSDOSFS_DPRINTF(("bytespersec %d secperclust %d " 14098dc8da5SEd Maste "secpertrack %d\n", pmp->pm_BytesPerSec, 14198dc8da5SEd Maste SecPerClust, pmp->pm_SecPerTrack)); 142237d1b14SEd Maste error = EINVAL; 143237d1b14SEd Maste goto error_exit; 144237d1b14SEd Maste } 145237d1b14SEd Maste 146237d1b14SEd Maste if (pmp->pm_Sectors == 0) { 147237d1b14SEd Maste pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); 148237d1b14SEd Maste pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); 149237d1b14SEd Maste } else { 150237d1b14SEd Maste pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); 151237d1b14SEd Maste pmp->pm_HugeSectors = pmp->pm_Sectors; 152237d1b14SEd Maste } 153237d1b14SEd Maste 15498dc8da5SEd Maste pmp->pm_flags = 0; 155237d1b14SEd Maste if (pmp->pm_RootDirEnts == 0) { 156237d1b14SEd Maste unsigned short vers = getushort(b710->bpbFSVers); 157237d1b14SEd Maste /* 158237d1b14SEd Maste * Some say that bsBootSectSig[23] must be zero, but 159237d1b14SEd Maste * Windows does not require this and some digital cameras 160237d1b14SEd Maste * do not set these to zero. Therefore, do not insist. 161237d1b14SEd Maste */ 162237d1b14SEd Maste if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) { 16398dc8da5SEd Maste MSDOSFS_DPRINTF(("sectors %d fatsecs %lu vers %d\n", 164237d1b14SEd Maste pmp->pm_Sectors, pmp->pm_FATsecs, vers)); 165237d1b14SEd Maste error = EINVAL; 166237d1b14SEd Maste goto error_exit; 167237d1b14SEd Maste } 168237d1b14SEd Maste pmp->pm_fatmask = FAT32_MASK; 169237d1b14SEd Maste pmp->pm_fatmult = 4; 170237d1b14SEd Maste pmp->pm_fatdiv = 1; 171237d1b14SEd Maste pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); 172237d1b14SEd Maste 173237d1b14SEd Maste /* mirrorring is enabled if the FATMIRROR bit is not set */ 174237d1b14SEd Maste if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0) 175237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 176237d1b14SEd Maste else 177237d1b14SEd Maste pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; 178237d1b14SEd Maste } else 179237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 180237d1b14SEd Maste 181237d1b14SEd Maste /* Check that fs has nonzero FAT size */ 182237d1b14SEd Maste if (pmp->pm_FATsecs == 0) { 18398dc8da5SEd Maste MSDOSFS_DPRINTF(("FATsecs is 0\n")); 184237d1b14SEd Maste error = EINVAL; 185237d1b14SEd Maste goto error_exit; 186237d1b14SEd Maste } 187237d1b14SEd Maste 188237d1b14SEd Maste pmp->pm_fatblk = pmp->pm_ResSectors; 189237d1b14SEd Maste if (FAT32(pmp)) { 190237d1b14SEd Maste pmp->pm_rootdirblk = getulong(b710->bpbRootClust); 191237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_fatblk 192237d1b14SEd Maste + (pmp->pm_FATs * pmp->pm_FATsecs); 193237d1b14SEd Maste pmp->pm_fsinfo = getushort(b710->bpbFSInfo); 194237d1b14SEd Maste } else { 195237d1b14SEd Maste pmp->pm_rootdirblk = pmp->pm_fatblk + 196237d1b14SEd Maste (pmp->pm_FATs * pmp->pm_FATsecs); 197237d1b14SEd Maste pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) 198237d1b14SEd Maste + pmp->pm_BytesPerSec - 1) 199237d1b14SEd Maste / pmp->pm_BytesPerSec;/* in sectors */ 200237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; 201237d1b14SEd Maste } 202237d1b14SEd Maste 20398dc8da5SEd Maste pmp->pm_maxcluster = ((pmp->pm_HugeSectors - pmp->pm_firstcluster) / 20498dc8da5SEd Maste SecPerClust) + 1; 205237d1b14SEd Maste pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; 206237d1b14SEd Maste 20798dc8da5SEd Maste if (pmp->pm_fatmask == 0) { 208237d1b14SEd Maste if (pmp->pm_maxcluster 209237d1b14SEd Maste <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { 210237d1b14SEd Maste /* 211237d1b14SEd Maste * This will usually be a floppy disk. This size makes 212237d1b14SEd Maste * sure that one FAT entry will not be split across 213237d1b14SEd Maste * multiple blocks. 214237d1b14SEd Maste */ 215237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 216237d1b14SEd Maste pmp->pm_fatmult = 3; 217237d1b14SEd Maste pmp->pm_fatdiv = 2; 218237d1b14SEd Maste } else { 219237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 220237d1b14SEd Maste pmp->pm_fatmult = 2; 221237d1b14SEd Maste pmp->pm_fatdiv = 1; 222237d1b14SEd Maste } 223237d1b14SEd Maste } 224237d1b14SEd Maste if (FAT12(pmp)) 225237d1b14SEd Maste pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; 226237d1b14SEd Maste else 227237d1b14SEd Maste pmp->pm_fatblocksize = MAXBSIZE; 228237d1b14SEd Maste 229237d1b14SEd Maste pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; 230237d1b14SEd Maste pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; 231237d1b14SEd Maste 232237d1b14SEd Maste /* 233237d1b14SEd Maste * Compute mask and shift value for isolating cluster relative byte 234237d1b14SEd Maste * offsets and cluster numbers from a file offset. 235237d1b14SEd Maste */ 236237d1b14SEd Maste pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec; 237237d1b14SEd Maste pmp->pm_crbomask = pmp->pm_bpcluster - 1; 238237d1b14SEd Maste pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; 239237d1b14SEd Maste 24098dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, " 24198dc8da5SEd Maste "fatblocksize=%lu, fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, " 24298dc8da5SEd Maste "crbomask=%lu, cnshift=%lu)\n", 24398dc8da5SEd Maste __func__, (unsigned long)pmp->pm_fatmask, pmp->pm_fatmult, 24498dc8da5SEd Maste pmp->pm_fatdiv, pmp->pm_fatblocksize, pmp->pm_fatblocksec, 24598dc8da5SEd Maste pmp->pm_bnshift, pmp->pm_bpcluster, pmp->pm_crbomask, 24698dc8da5SEd Maste pmp->pm_cnshift)); 247237d1b14SEd Maste /* 248237d1b14SEd Maste * Check for valid cluster size 249237d1b14SEd Maste * must be a power of 2 250237d1b14SEd Maste */ 251237d1b14SEd Maste if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { 25298dc8da5SEd Maste MSDOSFS_DPRINTF(("bpcluster %lu cnshift %lu\n", 253237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_cnshift)); 254237d1b14SEd Maste error = EINVAL; 255237d1b14SEd Maste goto error_exit; 256237d1b14SEd Maste } 257237d1b14SEd Maste 258237d1b14SEd Maste /* 259237d1b14SEd Maste * Release the bootsector buffer. 260237d1b14SEd Maste */ 2615b292f9aSEd Maste brelse(bp); 262237d1b14SEd Maste bp = NULL; 263237d1b14SEd Maste 264237d1b14SEd Maste /* 265237d1b14SEd Maste * Check FSInfo. 266237d1b14SEd Maste */ 267237d1b14SEd Maste if (pmp->pm_fsinfo) { 268237d1b14SEd Maste struct fsinfo *fp; 269237d1b14SEd Maste 270237d1b14SEd Maste /* 271237d1b14SEd Maste * XXX If the fsinfo block is stored on media with 272237d1b14SEd Maste * 2KB or larger sectors, is the fsinfo structure 273237d1b14SEd Maste * padded at the end or in the middle? 274237d1b14SEd Maste */ 27598dc8da5SEd Maste if ((error = bread(devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, 27698dc8da5SEd Maste 0, &bp)) != 0) 277237d1b14SEd Maste goto error_exit; 278237d1b14SEd Maste fp = (struct fsinfo *)bp->b_data; 279237d1b14SEd Maste if (!memcmp(fp->fsisig1, "RRaA", 4) 280237d1b14SEd Maste && !memcmp(fp->fsisig2, "rrAa", 4) 28198dc8da5SEd Maste && !memcmp(fp->fsisig3, "\0\0\125\252", 4)) 282237d1b14SEd Maste pmp->pm_nxtfree = getulong(fp->fsinxtfree); 283237d1b14SEd Maste else 284237d1b14SEd Maste pmp->pm_fsinfo = 0; 2855b292f9aSEd Maste brelse(bp); 286237d1b14SEd Maste bp = NULL; 287237d1b14SEd Maste } 288237d1b14SEd Maste 289237d1b14SEd Maste /* 290237d1b14SEd Maste * Check and validate (or perhaps invalidate?) the fsinfo structure? 291237d1b14SEd Maste * XXX 292237d1b14SEd Maste */ 293237d1b14SEd Maste if (pmp->pm_fsinfo) { 294237d1b14SEd Maste if ((pmp->pm_nxtfree == 0xffffffffUL) || 295237d1b14SEd Maste (pmp->pm_nxtfree > pmp->pm_maxcluster)) 296237d1b14SEd Maste pmp->pm_fsinfo = 0; 297237d1b14SEd Maste } 298237d1b14SEd Maste 299237d1b14SEd Maste /* 300237d1b14SEd Maste * Allocate memory for the bitmap of allocated clusters, and then 301237d1b14SEd Maste * fill it in. 302237d1b14SEd Maste */ 303237d1b14SEd Maste pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap), 304237d1b14SEd Maste ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS)); 305237d1b14SEd Maste /* 306237d1b14SEd Maste * fillinusemap() needs pm_devvp. 307237d1b14SEd Maste */ 308237d1b14SEd Maste pmp->pm_dev = 0; 309237d1b14SEd Maste pmp->pm_devvp = devvp; 310237d1b14SEd Maste 311237d1b14SEd Maste /* 312237d1b14SEd Maste * Have the inuse map filled in. 313237d1b14SEd Maste */ 314237d1b14SEd Maste if ((error = fillinusemap(pmp)) != 0) { 31598dc8da5SEd Maste MSDOSFS_DPRINTF(("fillinusemap %d\n", error)); 316237d1b14SEd Maste goto error_exit; 317237d1b14SEd Maste } 318237d1b14SEd Maste 319237d1b14SEd Maste /* 320237d1b14SEd Maste * Finish up. 321237d1b14SEd Maste */ 322237d1b14SEd Maste if (ronly) 323237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_RONLY; 324237d1b14SEd Maste else 325237d1b14SEd Maste pmp->pm_fmod = 1; 326237d1b14SEd Maste 327237d1b14SEd Maste /* 328237d1b14SEd Maste * If we ever do quotas for DOS filesystems this would be a place 329237d1b14SEd Maste * to fill in the info in the msdosfsmount structure. You dolt, 330237d1b14SEd Maste * quotas on dos filesystems make no sense because files have no 331237d1b14SEd Maste * owners on dos filesystems. of course there is some empty space 332237d1b14SEd Maste * in the directory entry where we could put uid's and gid's. 333237d1b14SEd Maste */ 334237d1b14SEd Maste 335237d1b14SEd Maste return pmp; 336237d1b14SEd Maste 337237d1b14SEd Maste error_exit: 338237d1b14SEd Maste if (bp) 33998dc8da5SEd Maste brelse(bp); 340237d1b14SEd Maste if (pmp) { 341237d1b14SEd Maste if (pmp->pm_inusemap) 342237d1b14SEd Maste free(pmp->pm_inusemap); 343237d1b14SEd Maste free(pmp); 344237d1b14SEd Maste } 345237d1b14SEd Maste errno = error; 346237d1b14SEd Maste return NULL; 347237d1b14SEd Maste } 348237d1b14SEd Maste 349237d1b14SEd Maste int 350237d1b14SEd Maste msdosfs_root(struct msdosfsmount *pmp, struct vnode *vp) { 351237d1b14SEd Maste struct denode *ndep; 352237d1b14SEd Maste int error; 353237d1b14SEd Maste 354237d1b14SEd Maste *vp = *pmp->pm_devvp; 355237d1b14SEd Maste if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0) { 356237d1b14SEd Maste errno = error; 357237d1b14SEd Maste return -1; 358237d1b14SEd Maste } 359237d1b14SEd Maste vp->v_data = ndep; 360237d1b14SEd Maste return 0; 361237d1b14SEd Maste } 3628651679aSXin LI 3638651679aSXin LI /* 3648651679aSXin LI * If we have an FSInfo block, update it. 3658651679aSXin LI */ 3668651679aSXin LI int 3678651679aSXin LI msdosfs_fsiflush(struct msdosfsmount *pmp) 3688651679aSXin LI { 3698651679aSXin LI struct fsinfo *fp; 3708651679aSXin LI struct buf *bp; 3718651679aSXin LI int error; 3728651679aSXin LI 3738651679aSXin LI if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) { 3748651679aSXin LI error = 0; 3758651679aSXin LI goto out; 3768651679aSXin LI } 3778651679aSXin LI error = bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, 3788651679aSXin LI NOCRED, &bp); 3798651679aSXin LI if (error != 0) { 3808651679aSXin LI brelse(bp); 3818651679aSXin LI goto out; 3828651679aSXin LI } 3838651679aSXin LI fp = (struct fsinfo *)bp->b_data; 3848651679aSXin LI putulong(fp->fsinfree, pmp->pm_freeclustercount); 3858651679aSXin LI putulong(fp->fsinxtfree, pmp->pm_nxtfree); 3868651679aSXin LI pmp->pm_flags &= ~MSDOSFS_FSIMOD; 3878651679aSXin LI error = bwrite(bp); 3888651679aSXin LI 3898651679aSXin LI out: 3908651679aSXin LI return (error); 3918651679aSXin LI } 392