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 #include <sys/cdefs.h> 49237d1b14SEd Maste /* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */ 50237d1b14SEd Maste __FBSDID("$FreeBSD$"); 51237d1b14SEd Maste 52237d1b14SEd Maste #include <sys/param.h> 53*98dc8da5SEd Maste #include <sys/mount.h> 54237d1b14SEd Maste 55237d1b14SEd Maste #include <errno.h> 56*98dc8da5SEd Maste #include <stdio.h> 57237d1b14SEd Maste #include <string.h> 58*98dc8da5SEd Maste #include <stdlib.h> 59237d1b14SEd Maste #include <util.h> 60237d1b14SEd Maste 61*98dc8da5SEd Maste #include <fs/msdosfs/bootsect.h> 62*98dc8da5SEd Maste #include <fs/msdosfs/bpb.h> 63*98dc8da5SEd Maste 64*98dc8da5SEd Maste #include <mkfs_msdos.h> 65*98dc8da5SEd Maste 66237d1b14SEd Maste #include "makefs.h" 67237d1b14SEd Maste #include "msdos.h" 68237d1b14SEd Maste 69*98dc8da5SEd Maste #include "ffs/buf.h" 70*98dc8da5SEd Maste 71*98dc8da5SEd Maste #include "msdos/denode.h" 72*98dc8da5SEd Maste #include "msdos/direntry.h" 73*98dc8da5SEd Maste #include "msdos/fat.h" 74*98dc8da5SEd Maste #include "msdos/msdosfsmount.h" 75237d1b14SEd Maste 76237d1b14SEd Maste struct msdosfsmount * 77*98dc8da5SEd Maste msdosfs_mount(struct vnode *devvp) 78237d1b14SEd Maste { 79237d1b14SEd Maste struct msdosfsmount *pmp = NULL; 80237d1b14SEd Maste struct buf *bp; 81237d1b14SEd Maste union bootsector *bsp; 82237d1b14SEd Maste struct byte_bpb33 *b33; 83237d1b14SEd Maste struct byte_bpb50 *b50; 84237d1b14SEd Maste struct byte_bpb710 *b710; 85237d1b14SEd Maste uint8_t SecPerClust; 86*98dc8da5SEd Maste int ronly = 0, error; 87237d1b14SEd Maste int bsize; 88237d1b14SEd Maste unsigned secsize = 512; 89237d1b14SEd Maste 90*98dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(bread 0)\n", __func__)); 91237d1b14SEd Maste if ((error = bread(devvp, 0, secsize, 0, &bp)) != 0) 92237d1b14SEd Maste goto error_exit; 93237d1b14SEd Maste 94237d1b14SEd Maste bsp = (union bootsector *)bp->b_data; 95237d1b14SEd Maste b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; 96237d1b14SEd Maste b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; 97237d1b14SEd Maste b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; 98237d1b14SEd Maste 99*98dc8da5SEd Maste if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 || 100*98dc8da5SEd Maste bsp->bs50.bsBootSectSig1 != BOOTSIG1) { 101*98dc8da5SEd Maste MSDOSFS_DPRINTF(("bootsig0 %d bootsig1 %d\n", 102237d1b14SEd Maste bsp->bs50.bsBootSectSig0, 103237d1b14SEd Maste bsp->bs50.bsBootSectSig1)); 104237d1b14SEd Maste error = EINVAL; 105237d1b14SEd Maste goto error_exit; 106237d1b14SEd Maste } 107237d1b14SEd Maste bsize = 0; 108237d1b14SEd Maste 109*98dc8da5SEd Maste pmp = ecalloc(1, sizeof(*pmp)); 110237d1b14SEd Maste /* 111237d1b14SEd Maste * Compute several useful quantities from the bpb in the 112237d1b14SEd Maste * bootsector. Copy in the dos 5 variant of the bpb then fix up 113237d1b14SEd Maste * the fields that are different between dos 5 and dos 3.3. 114237d1b14SEd Maste */ 115237d1b14SEd Maste SecPerClust = b50->bpbSecPerClust; 116237d1b14SEd Maste pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); 117237d1b14SEd Maste pmp->pm_ResSectors = getushort(b50->bpbResSectors); 118237d1b14SEd Maste pmp->pm_FATs = b50->bpbFATs; 119237d1b14SEd Maste pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); 120237d1b14SEd Maste pmp->pm_Sectors = getushort(b50->bpbSectors); 121237d1b14SEd Maste pmp->pm_FATsecs = getushort(b50->bpbFATsecs); 122237d1b14SEd Maste pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); 123237d1b14SEd Maste pmp->pm_Heads = getushort(b50->bpbHeads); 124237d1b14SEd Maste pmp->pm_Media = b50->bpbMedia; 125237d1b14SEd Maste 126*98dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, " 127*98dc8da5SEd Maste "RootDirEnts=%u, Sectors=%u, FATsecs=%lu, SecPerTrack=%u, " 128*98dc8da5SEd Maste "Heads=%u, Media=%u)\n", 129*98dc8da5SEd Maste __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, 130*98dc8da5SEd Maste pmp->pm_FATs, pmp->pm_RootDirEnts, pmp->pm_Sectors, 131*98dc8da5SEd Maste pmp->pm_FATsecs, pmp->pm_SecPerTrack, pmp->pm_Heads, 132*98dc8da5SEd Maste pmp->pm_Media)); 133*98dc8da5SEd Maste 134237d1b14SEd Maste /* XXX - We should probably check more values here */ 135237d1b14SEd Maste if (!pmp->pm_BytesPerSec || !SecPerClust 136237d1b14SEd Maste || pmp->pm_SecPerTrack > 63) { 137*98dc8da5SEd Maste MSDOSFS_DPRINTF(("bytespersec %d secperclust %d " 138*98dc8da5SEd Maste "secpertrack %d\n", pmp->pm_BytesPerSec, 139*98dc8da5SEd Maste SecPerClust, pmp->pm_SecPerTrack)); 140237d1b14SEd Maste error = EINVAL; 141237d1b14SEd Maste goto error_exit; 142237d1b14SEd Maste } 143237d1b14SEd Maste 144237d1b14SEd Maste if (pmp->pm_Sectors == 0) { 145237d1b14SEd Maste pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); 146237d1b14SEd Maste pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); 147237d1b14SEd Maste } else { 148237d1b14SEd Maste pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); 149237d1b14SEd Maste pmp->pm_HugeSectors = pmp->pm_Sectors; 150237d1b14SEd Maste } 151237d1b14SEd Maste 152*98dc8da5SEd Maste pmp->pm_flags = 0; 153237d1b14SEd Maste if (pmp->pm_RootDirEnts == 0) { 154237d1b14SEd Maste unsigned short vers = getushort(b710->bpbFSVers); 155237d1b14SEd Maste /* 156237d1b14SEd Maste * Some say that bsBootSectSig[23] must be zero, but 157237d1b14SEd Maste * Windows does not require this and some digital cameras 158237d1b14SEd Maste * do not set these to zero. Therefore, do not insist. 159237d1b14SEd Maste */ 160237d1b14SEd Maste if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) { 161*98dc8da5SEd Maste MSDOSFS_DPRINTF(("sectors %d fatsecs %lu vers %d\n", 162237d1b14SEd Maste pmp->pm_Sectors, pmp->pm_FATsecs, vers)); 163237d1b14SEd Maste error = EINVAL; 164237d1b14SEd Maste goto error_exit; 165237d1b14SEd Maste } 166237d1b14SEd Maste pmp->pm_fatmask = FAT32_MASK; 167237d1b14SEd Maste pmp->pm_fatmult = 4; 168237d1b14SEd Maste pmp->pm_fatdiv = 1; 169237d1b14SEd Maste pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); 170237d1b14SEd Maste 171237d1b14SEd Maste /* mirrorring is enabled if the FATMIRROR bit is not set */ 172237d1b14SEd Maste if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0) 173237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 174237d1b14SEd Maste else 175237d1b14SEd Maste pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; 176237d1b14SEd Maste } else 177237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 178237d1b14SEd Maste 179237d1b14SEd Maste /* Check that fs has nonzero FAT size */ 180237d1b14SEd Maste if (pmp->pm_FATsecs == 0) { 181*98dc8da5SEd Maste MSDOSFS_DPRINTF(("FATsecs is 0\n")); 182237d1b14SEd Maste error = EINVAL; 183237d1b14SEd Maste goto error_exit; 184237d1b14SEd Maste } 185237d1b14SEd Maste 186237d1b14SEd Maste pmp->pm_fatblk = pmp->pm_ResSectors; 187237d1b14SEd Maste if (FAT32(pmp)) { 188237d1b14SEd Maste pmp->pm_rootdirblk = getulong(b710->bpbRootClust); 189237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_fatblk 190237d1b14SEd Maste + (pmp->pm_FATs * pmp->pm_FATsecs); 191237d1b14SEd Maste pmp->pm_fsinfo = getushort(b710->bpbFSInfo); 192237d1b14SEd Maste } else { 193237d1b14SEd Maste pmp->pm_rootdirblk = pmp->pm_fatblk + 194237d1b14SEd Maste (pmp->pm_FATs * pmp->pm_FATsecs); 195237d1b14SEd Maste pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) 196237d1b14SEd Maste + pmp->pm_BytesPerSec - 1) 197237d1b14SEd Maste / pmp->pm_BytesPerSec;/* in sectors */ 198237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; 199237d1b14SEd Maste } 200237d1b14SEd Maste 201*98dc8da5SEd Maste pmp->pm_maxcluster = ((pmp->pm_HugeSectors - pmp->pm_firstcluster) / 202*98dc8da5SEd Maste SecPerClust) + 1; 203237d1b14SEd Maste pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; 204237d1b14SEd Maste 205*98dc8da5SEd Maste if (pmp->pm_fatmask == 0) { 206237d1b14SEd Maste if (pmp->pm_maxcluster 207237d1b14SEd Maste <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { 208237d1b14SEd Maste /* 209237d1b14SEd Maste * This will usually be a floppy disk. This size makes 210237d1b14SEd Maste * sure that one FAT entry will not be split across 211237d1b14SEd Maste * multiple blocks. 212237d1b14SEd Maste */ 213237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 214237d1b14SEd Maste pmp->pm_fatmult = 3; 215237d1b14SEd Maste pmp->pm_fatdiv = 2; 216237d1b14SEd Maste } else { 217237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 218237d1b14SEd Maste pmp->pm_fatmult = 2; 219237d1b14SEd Maste pmp->pm_fatdiv = 1; 220237d1b14SEd Maste } 221237d1b14SEd Maste } 222237d1b14SEd Maste if (FAT12(pmp)) 223237d1b14SEd Maste pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; 224237d1b14SEd Maste else 225237d1b14SEd Maste pmp->pm_fatblocksize = MAXBSIZE; 226237d1b14SEd Maste 227237d1b14SEd Maste pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; 228237d1b14SEd Maste pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; 229237d1b14SEd Maste 230237d1b14SEd Maste /* 231237d1b14SEd Maste * Compute mask and shift value for isolating cluster relative byte 232237d1b14SEd Maste * offsets and cluster numbers from a file offset. 233237d1b14SEd Maste */ 234237d1b14SEd Maste pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec; 235237d1b14SEd Maste pmp->pm_crbomask = pmp->pm_bpcluster - 1; 236237d1b14SEd Maste pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; 237237d1b14SEd Maste 238*98dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, " 239*98dc8da5SEd Maste "fatblocksize=%lu, fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, " 240*98dc8da5SEd Maste "crbomask=%lu, cnshift=%lu)\n", 241*98dc8da5SEd Maste __func__, (unsigned long)pmp->pm_fatmask, pmp->pm_fatmult, 242*98dc8da5SEd Maste pmp->pm_fatdiv, pmp->pm_fatblocksize, pmp->pm_fatblocksec, 243*98dc8da5SEd Maste pmp->pm_bnshift, pmp->pm_bpcluster, pmp->pm_crbomask, 244*98dc8da5SEd Maste pmp->pm_cnshift)); 245237d1b14SEd Maste /* 246237d1b14SEd Maste * Check for valid cluster size 247237d1b14SEd Maste * must be a power of 2 248237d1b14SEd Maste */ 249237d1b14SEd Maste if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { 250*98dc8da5SEd Maste MSDOSFS_DPRINTF(("bpcluster %lu cnshift %lu\n", 251237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_cnshift)); 252237d1b14SEd Maste error = EINVAL; 253237d1b14SEd Maste goto error_exit; 254237d1b14SEd Maste } 255237d1b14SEd Maste 256237d1b14SEd Maste /* 257237d1b14SEd Maste * Release the bootsector buffer. 258237d1b14SEd Maste */ 2595b292f9aSEd Maste brelse(bp); 260237d1b14SEd Maste bp = NULL; 261237d1b14SEd Maste 262237d1b14SEd Maste /* 263237d1b14SEd Maste * Check FSInfo. 264237d1b14SEd Maste */ 265237d1b14SEd Maste if (pmp->pm_fsinfo) { 266237d1b14SEd Maste struct fsinfo *fp; 267237d1b14SEd Maste 268237d1b14SEd Maste /* 269237d1b14SEd Maste * XXX If the fsinfo block is stored on media with 270237d1b14SEd Maste * 2KB or larger sectors, is the fsinfo structure 271237d1b14SEd Maste * padded at the end or in the middle? 272237d1b14SEd Maste */ 273*98dc8da5SEd Maste if ((error = bread(devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, 274*98dc8da5SEd Maste 0, &bp)) != 0) 275237d1b14SEd Maste goto error_exit; 276237d1b14SEd Maste fp = (struct fsinfo *)bp->b_data; 277237d1b14SEd Maste if (!memcmp(fp->fsisig1, "RRaA", 4) 278237d1b14SEd Maste && !memcmp(fp->fsisig2, "rrAa", 4) 279*98dc8da5SEd Maste && !memcmp(fp->fsisig3, "\0\0\125\252", 4)) 280237d1b14SEd Maste pmp->pm_nxtfree = getulong(fp->fsinxtfree); 281237d1b14SEd Maste else 282237d1b14SEd Maste pmp->pm_fsinfo = 0; 2835b292f9aSEd Maste brelse(bp); 284237d1b14SEd Maste bp = NULL; 285237d1b14SEd Maste } 286237d1b14SEd Maste 287237d1b14SEd Maste /* 288237d1b14SEd Maste * Check and validate (or perhaps invalidate?) the fsinfo structure? 289237d1b14SEd Maste * XXX 290237d1b14SEd Maste */ 291237d1b14SEd Maste if (pmp->pm_fsinfo) { 292237d1b14SEd Maste if ((pmp->pm_nxtfree == 0xffffffffUL) || 293237d1b14SEd Maste (pmp->pm_nxtfree > pmp->pm_maxcluster)) 294237d1b14SEd Maste pmp->pm_fsinfo = 0; 295237d1b14SEd Maste } 296237d1b14SEd Maste 297237d1b14SEd Maste /* 298237d1b14SEd Maste * Allocate memory for the bitmap of allocated clusters, and then 299237d1b14SEd Maste * fill it in. 300237d1b14SEd Maste */ 301237d1b14SEd Maste pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap), 302237d1b14SEd Maste ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS)); 303237d1b14SEd Maste /* 304237d1b14SEd Maste * fillinusemap() needs pm_devvp. 305237d1b14SEd Maste */ 306237d1b14SEd Maste pmp->pm_dev = 0; 307237d1b14SEd Maste pmp->pm_devvp = devvp; 308237d1b14SEd Maste 309237d1b14SEd Maste /* 310237d1b14SEd Maste * Have the inuse map filled in. 311237d1b14SEd Maste */ 312237d1b14SEd Maste if ((error = fillinusemap(pmp)) != 0) { 313*98dc8da5SEd Maste MSDOSFS_DPRINTF(("fillinusemap %d\n", error)); 314237d1b14SEd Maste goto error_exit; 315237d1b14SEd Maste } 316237d1b14SEd Maste 317237d1b14SEd Maste /* 318237d1b14SEd Maste * Finish up. 319237d1b14SEd Maste */ 320237d1b14SEd Maste if (ronly) 321237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_RONLY; 322237d1b14SEd Maste else 323237d1b14SEd Maste pmp->pm_fmod = 1; 324237d1b14SEd Maste 325237d1b14SEd Maste /* 326237d1b14SEd Maste * If we ever do quotas for DOS filesystems this would be a place 327237d1b14SEd Maste * to fill in the info in the msdosfsmount structure. You dolt, 328237d1b14SEd Maste * quotas on dos filesystems make no sense because files have no 329237d1b14SEd Maste * owners on dos filesystems. of course there is some empty space 330237d1b14SEd Maste * in the directory entry where we could put uid's and gid's. 331237d1b14SEd Maste */ 332237d1b14SEd Maste 333237d1b14SEd Maste return pmp; 334237d1b14SEd Maste 335237d1b14SEd Maste error_exit: 336237d1b14SEd Maste if (bp) 337*98dc8da5SEd Maste brelse(bp); 338237d1b14SEd Maste if (pmp) { 339237d1b14SEd Maste if (pmp->pm_inusemap) 340237d1b14SEd Maste free(pmp->pm_inusemap); 341237d1b14SEd Maste free(pmp); 342237d1b14SEd Maste } 343237d1b14SEd Maste errno = error; 344237d1b14SEd Maste return NULL; 345237d1b14SEd Maste } 346237d1b14SEd Maste 347237d1b14SEd Maste int 348237d1b14SEd Maste msdosfs_root(struct msdosfsmount *pmp, struct vnode *vp) { 349237d1b14SEd Maste struct denode *ndep; 350237d1b14SEd Maste int error; 351237d1b14SEd Maste 352237d1b14SEd Maste *vp = *pmp->pm_devvp; 353237d1b14SEd Maste if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0) { 354237d1b14SEd Maste errno = error; 355237d1b14SEd Maste return -1; 356237d1b14SEd Maste } 357237d1b14SEd Maste vp->v_data = ndep; 358237d1b14SEd Maste return 0; 359237d1b14SEd Maste } 360