1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * VFS operations for High Sierra filesystem 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/isa_defs.h> 35*0Sstevel@tonic-gate #include <sys/t_lock.h> 36*0Sstevel@tonic-gate #include <sys/param.h> 37*0Sstevel@tonic-gate #include <sys/systm.h> 38*0Sstevel@tonic-gate #include <sys/sysmacros.h> 39*0Sstevel@tonic-gate #include <sys/kmem.h> 40*0Sstevel@tonic-gate #include <sys/signal.h> 41*0Sstevel@tonic-gate #include <sys/user.h> 42*0Sstevel@tonic-gate #include <sys/proc.h> 43*0Sstevel@tonic-gate #include <sys/disp.h> 44*0Sstevel@tonic-gate #include <sys/buf.h> 45*0Sstevel@tonic-gate #include <sys/pathname.h> 46*0Sstevel@tonic-gate #include <sys/vfs.h> 47*0Sstevel@tonic-gate #include <sys/vnode.h> 48*0Sstevel@tonic-gate #include <sys/file.h> 49*0Sstevel@tonic-gate #include <sys/uio.h> 50*0Sstevel@tonic-gate #include <sys/conf.h> 51*0Sstevel@tonic-gate #include <sys/policy.h> 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #include <vm/page.h> 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate #include <sys/fs/snode.h> 56*0Sstevel@tonic-gate #include <sys/fs/hsfs_spec.h> 57*0Sstevel@tonic-gate #include <sys/fs/hsfs_isospec.h> 58*0Sstevel@tonic-gate #include <sys/fs/hsfs_node.h> 59*0Sstevel@tonic-gate #include <sys/fs/hsfs_impl.h> 60*0Sstevel@tonic-gate #include <sys/fs/hsfs_susp.h> 61*0Sstevel@tonic-gate #include <sys/fs/hsfs_rrip.h> 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #include <sys/statvfs.h> 64*0Sstevel@tonic-gate #include <sys/mount.h> 65*0Sstevel@tonic-gate #include <sys/mntent.h> 66*0Sstevel@tonic-gate #include <sys/swap.h> 67*0Sstevel@tonic-gate #include <sys/errno.h> 68*0Sstevel@tonic-gate #include <sys/debug.h> 69*0Sstevel@tonic-gate #include "fs/fs_subr.h" 70*0Sstevel@tonic-gate #include <sys/cmn_err.h> 71*0Sstevel@tonic-gate #include <sys/bootconf.h> 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * These are needed for the CDROMREADOFFSET Code 75*0Sstevel@tonic-gate */ 76*0Sstevel@tonic-gate #include <sys/cdio.h> 77*0Sstevel@tonic-gate #include <sys/sunddi.h> 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate #define HSFS_CLKSET 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate #include <sys/modctl.h> 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * Options for mount. 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate #define HOPT_GLOBAL MNTOPT_GLOBAL 87*0Sstevel@tonic-gate #define HOPT_NOGLOBAL MNTOPT_NOGLOBAL 88*0Sstevel@tonic-gate #define HOPT_MAPLCASE "maplcase" 89*0Sstevel@tonic-gate #define HOPT_NOMAPLCASE "nomaplcase" 90*0Sstevel@tonic-gate #define HOPT_NOTRAILDOT "notraildot" 91*0Sstevel@tonic-gate #define HOPT_TRAILDOT "traildot" 92*0Sstevel@tonic-gate #define HOPT_NRR "nrr" 93*0Sstevel@tonic-gate #define HOPT_RR "rr" 94*0Sstevel@tonic-gate #define HOPT_RO MNTOPT_RO 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate static char *global_cancel[] = { HOPT_NOGLOBAL, NULL }; 97*0Sstevel@tonic-gate static char *noglobal_cancel[] = { HOPT_GLOBAL, NULL }; 98*0Sstevel@tonic-gate static char *mapl_cancel[] = { HOPT_NOMAPLCASE, NULL }; 99*0Sstevel@tonic-gate static char *nomapl_cancel[] = { HOPT_MAPLCASE, NULL }; 100*0Sstevel@tonic-gate static char *ro_cancel[] = { MNTOPT_RW, NULL }; 101*0Sstevel@tonic-gate static char *rr_cancel[] = { HOPT_NRR, NULL }; 102*0Sstevel@tonic-gate static char *nrr_cancel[] = { HOPT_RR, NULL }; 103*0Sstevel@tonic-gate static char *trail_cancel[] = { HOPT_NOTRAILDOT, NULL }; 104*0Sstevel@tonic-gate static char *notrail_cancel[] = { HOPT_TRAILDOT, NULL }; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate static mntopt_t hsfs_options[] = { 107*0Sstevel@tonic-gate { HOPT_GLOBAL, global_cancel, NULL, 0, NULL }, 108*0Sstevel@tonic-gate { HOPT_NOGLOBAL, noglobal_cancel, NULL, MO_DEFAULT, NULL }, 109*0Sstevel@tonic-gate { HOPT_MAPLCASE, mapl_cancel, NULL, MO_DEFAULT, NULL }, 110*0Sstevel@tonic-gate { HOPT_NOMAPLCASE, nomapl_cancel, NULL, 0, NULL }, 111*0Sstevel@tonic-gate { HOPT_RO, ro_cancel, NULL, MO_DEFAULT, NULL }, 112*0Sstevel@tonic-gate { HOPT_RR, rr_cancel, NULL, MO_DEFAULT, NULL }, 113*0Sstevel@tonic-gate { HOPT_NRR, nrr_cancel, NULL, 0, NULL }, 114*0Sstevel@tonic-gate { HOPT_TRAILDOT, trail_cancel, NULL, MO_DEFAULT, NULL }, 115*0Sstevel@tonic-gate { HOPT_NOTRAILDOT, notrail_cancel, NULL, 0, NULL }, 116*0Sstevel@tonic-gate }; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate static mntopts_t hsfs_proto_opttbl = { 119*0Sstevel@tonic-gate sizeof (hsfs_options) / sizeof (mntopt_t), 120*0Sstevel@tonic-gate hsfs_options 121*0Sstevel@tonic-gate }; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate static int hsfsinit(int, char *); 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate static vfsdef_t vfw = { 126*0Sstevel@tonic-gate VFSDEF_VERSION, 127*0Sstevel@tonic-gate "hsfs", 128*0Sstevel@tonic-gate hsfsinit, 129*0Sstevel@tonic-gate VSW_HASPROTO, /* We don't suppport remounting */ 130*0Sstevel@tonic-gate &hsfs_proto_opttbl 131*0Sstevel@tonic-gate }; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate static struct modlfs modlfs = { 134*0Sstevel@tonic-gate &mod_fsops, "filesystem for HSFS", &vfw 135*0Sstevel@tonic-gate }; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 138*0Sstevel@tonic-gate MODREV_1, (void *)&modlfs, NULL 139*0Sstevel@tonic-gate }; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate char _depends_on[] = "fs/specfs"; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate int 144*0Sstevel@tonic-gate _init() 145*0Sstevel@tonic-gate { 146*0Sstevel@tonic-gate return (mod_install(&modlinkage)); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate int 150*0Sstevel@tonic-gate _fini() 151*0Sstevel@tonic-gate { 152*0Sstevel@tonic-gate return (EBUSY); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate int 156*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 157*0Sstevel@tonic-gate { 158*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate #define BDEVFLAG(dev) ((devopsp[getmajor(dev)])->devo_cb_ops->cb_flag) 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate kmutex_t hs_mounttab_lock; 164*0Sstevel@tonic-gate struct hsfs *hs_mounttab = NULL; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* default mode, uid, gid */ 167*0Sstevel@tonic-gate mode_t hsfs_default_mode = 0555; 168*0Sstevel@tonic-gate uid_t hsfs_default_uid = 0; 169*0Sstevel@tonic-gate gid_t hsfs_default_gid = 3; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate static int hsfs_mount(struct vfs *vfsp, struct vnode *mvp, 172*0Sstevel@tonic-gate struct mounta *uap, struct cred *cr); 173*0Sstevel@tonic-gate static int hsfs_unmount(struct vfs *vfsp, int, struct cred *cr); 174*0Sstevel@tonic-gate static int hsfs_root(struct vfs *vfsp, struct vnode **vpp); 175*0Sstevel@tonic-gate static int hsfs_statvfs(struct vfs *vfsp, struct statvfs64 *sbp); 176*0Sstevel@tonic-gate static int hsfs_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp); 177*0Sstevel@tonic-gate static int hsfs_mountroot(struct vfs *, enum whymountroot); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate static int hs_mountfs(struct vfs *vfsp, dev_t dev, char *path, 180*0Sstevel@tonic-gate mode_t mode, int flags, struct cred *cr, int isroot); 181*0Sstevel@tonic-gate static int hs_findhsvol(struct hsfs *fsp, struct vnode *vp, 182*0Sstevel@tonic-gate struct hs_volume *hvp); 183*0Sstevel@tonic-gate static int hs_parsehsvol(struct hsfs *fsp, uchar_t *volp, 184*0Sstevel@tonic-gate struct hs_volume *hvp); 185*0Sstevel@tonic-gate static int hs_findisovol(struct hsfs *fsp, struct vnode *vp, 186*0Sstevel@tonic-gate struct hs_volume *hvp); 187*0Sstevel@tonic-gate static int hs_parseisovol(struct hsfs *fsp, uchar_t *volp, 188*0Sstevel@tonic-gate struct hs_volume *hvp); 189*0Sstevel@tonic-gate static void hs_copylabel(struct hs_volume *, unsigned char *); 190*0Sstevel@tonic-gate static int hs_getmdev(struct vfs *, char *fspec, int flags, dev_t *pdev, 191*0Sstevel@tonic-gate mode_t *mode, cred_t *cr); 192*0Sstevel@tonic-gate static int hs_findvoldesc(dev_t rdev, int desc_sec); 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate static int hsfsfstype; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate static int 197*0Sstevel@tonic-gate hsfsinit(int fstype, char *name) 198*0Sstevel@tonic-gate { 199*0Sstevel@tonic-gate static const fs_operation_def_t hsfs_vfsops_template[] = { 200*0Sstevel@tonic-gate VFSNAME_MOUNT, hsfs_mount, 201*0Sstevel@tonic-gate VFSNAME_UNMOUNT, hsfs_unmount, 202*0Sstevel@tonic-gate VFSNAME_ROOT, hsfs_root, 203*0Sstevel@tonic-gate VFSNAME_STATVFS, hsfs_statvfs, 204*0Sstevel@tonic-gate VFSNAME_VGET, hsfs_vget, 205*0Sstevel@tonic-gate VFSNAME_MOUNTROOT, hsfs_mountroot, 206*0Sstevel@tonic-gate NULL, NULL 207*0Sstevel@tonic-gate }; 208*0Sstevel@tonic-gate int error; 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate error = vfs_setfsops(fstype, hsfs_vfsops_template, NULL); 211*0Sstevel@tonic-gate if (error != 0) { 212*0Sstevel@tonic-gate cmn_err(CE_WARN, "hsfsinit: bad vfs ops template"); 213*0Sstevel@tonic-gate return (error); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate error = vn_make_ops(name, hsfs_vnodeops_template, &hsfs_vnodeops); 217*0Sstevel@tonic-gate if (error != 0) { 218*0Sstevel@tonic-gate (void) vfs_freevfsops_by_type(fstype); 219*0Sstevel@tonic-gate cmn_err(CE_WARN, "hsfsinit: bad vnode ops template"); 220*0Sstevel@tonic-gate return (error); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate hsfsfstype = fstype; 224*0Sstevel@tonic-gate mutex_init(&hs_mounttab_lock, NULL, MUTEX_DEFAULT, NULL); 225*0Sstevel@tonic-gate hs_init_hsnode_cache(); 226*0Sstevel@tonic-gate return (0); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /*ARGSUSED*/ 230*0Sstevel@tonic-gate static int 231*0Sstevel@tonic-gate hsfs_mount(struct vfs *vfsp, struct vnode *mvp, 232*0Sstevel@tonic-gate struct mounta *uap, struct cred *cr) 233*0Sstevel@tonic-gate { 234*0Sstevel@tonic-gate int vnode_busy; 235*0Sstevel@tonic-gate dev_t dev; 236*0Sstevel@tonic-gate struct pathname dpn; 237*0Sstevel@tonic-gate int error; 238*0Sstevel@tonic-gate mode_t mode; 239*0Sstevel@tonic-gate int flags; /* this will hold the mount specific data */ 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) 242*0Sstevel@tonic-gate return (error); 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate if (mvp->v_type != VDIR) 245*0Sstevel@tonic-gate return (ENOTDIR); 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* mount option must be read only, else mount will be rejected */ 248*0Sstevel@tonic-gate if (!(uap->flags & MS_RDONLY)) 249*0Sstevel@tonic-gate return (EROFS); 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate /* 252*0Sstevel@tonic-gate * We already told the framework that we don't support remounting. 253*0Sstevel@tonic-gate */ 254*0Sstevel@tonic-gate ASSERT(!(uap->flags & MS_REMOUNT)); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate mutex_enter(&mvp->v_lock); 257*0Sstevel@tonic-gate vnode_busy = (mvp->v_count != 1) || (mvp->v_flag & VROOT); 258*0Sstevel@tonic-gate mutex_exit(&mvp->v_lock); 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate if ((uap->flags & MS_OVERLAY) == 0 && vnode_busy) { 261*0Sstevel@tonic-gate return (EBUSY); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate /* 265*0Sstevel@tonic-gate * Check for the options that actually affect things 266*0Sstevel@tonic-gate * at our level. 267*0Sstevel@tonic-gate */ 268*0Sstevel@tonic-gate flags = 0; 269*0Sstevel@tonic-gate if (vfs_optionisset(vfsp, HOPT_NOMAPLCASE, NULL)) 270*0Sstevel@tonic-gate flags |= HSFSMNT_NOMAPLCASE; 271*0Sstevel@tonic-gate if (vfs_optionisset(vfsp, HOPT_NOTRAILDOT, NULL)) 272*0Sstevel@tonic-gate flags |= HSFSMNT_NOTRAILDOT; 273*0Sstevel@tonic-gate if (vfs_optionisset(vfsp, HOPT_NRR, NULL)) 274*0Sstevel@tonic-gate flags |= HSFSMNT_NORRIP; 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate error = pn_get(uap->dir, (uap->flags & MS_SYSSPACE) ? 277*0Sstevel@tonic-gate UIO_SYSSPACE : UIO_USERSPACE, &dpn); 278*0Sstevel@tonic-gate if (error) 279*0Sstevel@tonic-gate return (error); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate if ((error = hs_getmdev(vfsp, uap->spec, uap->flags, &dev, 282*0Sstevel@tonic-gate &mode, cr)) != 0) { 283*0Sstevel@tonic-gate pn_free(&dpn); 284*0Sstevel@tonic-gate return (error); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* 288*0Sstevel@tonic-gate * If the device is a tape, return error 289*0Sstevel@tonic-gate */ 290*0Sstevel@tonic-gate if ((BDEVFLAG(dev) & D_TAPE) == D_TAPE) { 291*0Sstevel@tonic-gate pn_free(&dpn); 292*0Sstevel@tonic-gate return (ENOTBLK); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate /* 296*0Sstevel@tonic-gate * Mount the filesystem. 297*0Sstevel@tonic-gate */ 298*0Sstevel@tonic-gate error = hs_mountfs(vfsp, dev, dpn.pn_path, mode, flags, cr, 0); 299*0Sstevel@tonic-gate pn_free(&dpn); 300*0Sstevel@tonic-gate return (error); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /*ARGSUSED*/ 304*0Sstevel@tonic-gate static int 305*0Sstevel@tonic-gate hsfs_unmount( 306*0Sstevel@tonic-gate struct vfs *vfsp, 307*0Sstevel@tonic-gate int flag, 308*0Sstevel@tonic-gate struct cred *cr) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate struct hsfs **tspp; 311*0Sstevel@tonic-gate struct hsfs *fsp; 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate if (secpolicy_fs_unmount(cr, vfsp) != 0) 314*0Sstevel@tonic-gate return (EPERM); 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* 317*0Sstevel@tonic-gate * forced unmount is not supported by this file system 318*0Sstevel@tonic-gate * and thus, ENOTSUP is being returned. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate if (flag & MS_FORCE) 321*0Sstevel@tonic-gate return (ENOTSUP); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate fsp = VFS_TO_HSFS(vfsp); 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate if (fsp->hsfs_rootvp->v_count != 1) 326*0Sstevel@tonic-gate return (EBUSY); 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate /* destroy all old pages and hsnodes for this vfs */ 329*0Sstevel@tonic-gate if (hs_synchash(vfsp)) 330*0Sstevel@tonic-gate return (EBUSY); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate mutex_enter(&hs_mounttab_lock); 333*0Sstevel@tonic-gate for (tspp = &hs_mounttab; *tspp != NULL; tspp = &(*tspp)->hsfs_next) { 334*0Sstevel@tonic-gate if (*tspp == fsp) 335*0Sstevel@tonic-gate break; 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate if (*tspp == NULL) { 338*0Sstevel@tonic-gate mutex_exit(&hs_mounttab_lock); 339*0Sstevel@tonic-gate panic("hsfs_unmount: vfs not mounted?"); 340*0Sstevel@tonic-gate /*NOTREACHED*/ 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate *tspp = fsp->hsfs_next; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate mutex_exit(&hs_mounttab_lock); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate (void) VOP_CLOSE(fsp->hsfs_devvp, FREAD, 1, (offset_t)0, cr); 348*0Sstevel@tonic-gate VN_RELE(fsp->hsfs_devvp); 349*0Sstevel@tonic-gate /* free path table space */ 350*0Sstevel@tonic-gate if (fsp->hsfs_ptbl != NULL) 351*0Sstevel@tonic-gate kmem_free(fsp->hsfs_ptbl, 352*0Sstevel@tonic-gate (size_t)fsp->hsfs_vol.ptbl_len); 353*0Sstevel@tonic-gate /* free path table index table */ 354*0Sstevel@tonic-gate if (fsp->hsfs_ptbl_idx != NULL) 355*0Sstevel@tonic-gate kmem_free(fsp->hsfs_ptbl_idx, (size_t) 356*0Sstevel@tonic-gate (fsp->hsfs_ptbl_idx_size * sizeof (struct ptable_idx))); 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate /* free "mounted on" pathame */ 359*0Sstevel@tonic-gate if (fsp->hsfs_fsmnt != NULL) 360*0Sstevel@tonic-gate kmem_free(fsp->hsfs_fsmnt, strlen(fsp->hsfs_fsmnt) + 1); 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate mutex_destroy(&fsp->hsfs_free_lock); 363*0Sstevel@tonic-gate rw_destroy(&fsp->hsfs_hash_lock); 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate kmem_free(fsp, sizeof (*fsp)); 366*0Sstevel@tonic-gate return (0); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate /*ARGSUSED*/ 370*0Sstevel@tonic-gate static int 371*0Sstevel@tonic-gate hsfs_root(struct vfs *vfsp, struct vnode **vpp) 372*0Sstevel@tonic-gate { 373*0Sstevel@tonic-gate *vpp = (VFS_TO_HSFS(vfsp))->hsfs_rootvp; 374*0Sstevel@tonic-gate VN_HOLD(*vpp); 375*0Sstevel@tonic-gate return (0); 376*0Sstevel@tonic-gate } 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate /*ARGSUSED*/ 379*0Sstevel@tonic-gate static int 380*0Sstevel@tonic-gate hsfs_statvfs(struct vfs *vfsp, struct statvfs64 *sbp) 381*0Sstevel@tonic-gate { 382*0Sstevel@tonic-gate struct hsfs *fsp; 383*0Sstevel@tonic-gate dev32_t d32; 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate fsp = VFS_TO_HSFS(vfsp); 386*0Sstevel@tonic-gate if (fsp->hsfs_magic != HSFS_MAGIC) 387*0Sstevel@tonic-gate return (EINVAL); 388*0Sstevel@tonic-gate bzero(sbp, sizeof (*sbp)); 389*0Sstevel@tonic-gate sbp->f_bsize = vfsp->vfs_bsize; 390*0Sstevel@tonic-gate sbp->f_frsize = sbp->f_bsize; /* no fragment, same as block size */ 391*0Sstevel@tonic-gate sbp->f_blocks = (fsblkcnt64_t)fsp->hsfs_vol.vol_size; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate sbp->f_bfree = (fsblkcnt64_t)0; 394*0Sstevel@tonic-gate sbp->f_bavail = (fsblkcnt64_t)0; 395*0Sstevel@tonic-gate sbp->f_files = (fsfilcnt64_t)-1; 396*0Sstevel@tonic-gate sbp->f_ffree = (fsfilcnt64_t)0; 397*0Sstevel@tonic-gate sbp->f_favail = (fsfilcnt64_t)0; 398*0Sstevel@tonic-gate (void) cmpldev(&d32, vfsp->vfs_dev); 399*0Sstevel@tonic-gate sbp->f_fsid = d32; 400*0Sstevel@tonic-gate (void) strcpy(sbp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 401*0Sstevel@tonic-gate sbp->f_flag = vf_to_stf(vfsp->vfs_flag); 402*0Sstevel@tonic-gate sbp->f_namemax = fsp->hsfs_namemax; 403*0Sstevel@tonic-gate (void) strcpy(sbp->f_fstr, fsp->hsfs_vol.vol_id); 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate return (0); 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate /* 409*0Sstevel@tonic-gate * Previously nodeid was declared as uint32_t. This has been changed 410*0Sstevel@tonic-gate * to conform better with the ISO9660 standard. The standard states that 411*0Sstevel@tonic-gate * a LBN can be a 32 bit number, as the MAKE_NODEID macro shifts this 412*0Sstevel@tonic-gate * LBN 11 places left (LBN_TO_BYTE) and then shifts the result 5 right 413*0Sstevel@tonic-gate * (divide by 32) we are left with the potential of an overflow if 414*0Sstevel@tonic-gate * confined to a 32 bit value. 415*0Sstevel@tonic-gate */ 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate static int 418*0Sstevel@tonic-gate hsfs_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp) 419*0Sstevel@tonic-gate { 420*0Sstevel@tonic-gate struct hsfid *fid; 421*0Sstevel@tonic-gate struct hsfs *fsp; 422*0Sstevel@tonic-gate ino64_t nodeid; 423*0Sstevel@tonic-gate int error; 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate fsp = (struct hsfs *)VFS_TO_HSFS(vfsp); 426*0Sstevel@tonic-gate fid = (struct hsfid *)fidp; 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate /* 429*0Sstevel@tonic-gate * Look for vnode on hashlist. 430*0Sstevel@tonic-gate * If found, it's now active and the refcnt was incremented. 431*0Sstevel@tonic-gate */ 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate rw_enter(&fsp->hsfs_hash_lock, RW_READER); 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate nodeid = (ino64_t)MAKE_NODEID(fid->hf_dir_lbn, fid->hf_dir_off, vfsp); 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate if ((*vpp = hs_findhash(nodeid, vfsp)) == NULL) { 438*0Sstevel@tonic-gate /* 439*0Sstevel@tonic-gate * Not in cache, so we need to remake it. 440*0Sstevel@tonic-gate * hs_remakenode() will read the directory entry 441*0Sstevel@tonic-gate * and then check again to see if anyone else has 442*0Sstevel@tonic-gate * put it in the cache. 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate rw_exit(&fsp->hsfs_hash_lock); 445*0Sstevel@tonic-gate error = hs_remakenode(fid->hf_dir_lbn, (uint_t)fid->hf_dir_off, 446*0Sstevel@tonic-gate vfsp, vpp); 447*0Sstevel@tonic-gate return (error); 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate rw_exit(&fsp->hsfs_hash_lock); 450*0Sstevel@tonic-gate return (0); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate #define CHECKSUM_SIZE (64 * 1024) 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate /* 457*0Sstevel@tonic-gate * Compute a CD-ROM fsid by checksumming the first 64K of data on the CD 458*0Sstevel@tonic-gate * We use the 'fsp' argument to determine the location of the root 459*0Sstevel@tonic-gate * directory entry, and we start reading from there. 460*0Sstevel@tonic-gate */ 461*0Sstevel@tonic-gate static int 462*0Sstevel@tonic-gate compute_cdrom_id(struct hsfs *fsp, vnode_t *devvp) 463*0Sstevel@tonic-gate { 464*0Sstevel@tonic-gate uint_t secno; 465*0Sstevel@tonic-gate struct hs_volume *hsvp = &fsp->hsfs_vol; 466*0Sstevel@tonic-gate struct buf *bp; 467*0Sstevel@tonic-gate int error; 468*0Sstevel@tonic-gate int fsid; 469*0Sstevel@tonic-gate int size = CHECKSUM_SIZE; 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate secno = hsvp->root_dir.ext_lbn >> hsvp->lbn_secshift; 472*0Sstevel@tonic-gate bp = bread(devvp->v_rdev, secno * 4, size); 473*0Sstevel@tonic-gate error = geterror(bp); 474*0Sstevel@tonic-gate if (!error) { 475*0Sstevel@tonic-gate int *ibuf = (int *)bp->b_un.b_addr; 476*0Sstevel@tonic-gate int isize = size / sizeof (int); 477*0Sstevel@tonic-gate int i; 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate fsid = 0; 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate for (i = 0; i < isize; i++) 482*0Sstevel@tonic-gate fsid ^= ibuf[ i ]; 483*0Sstevel@tonic-gate } else /* use creation date */ 484*0Sstevel@tonic-gate fsid = hsvp->cre_date.tv_sec; 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate brelse(bp); 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate return (fsid); 489*0Sstevel@tonic-gate } 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate /*ARGSUSED*/ 493*0Sstevel@tonic-gate static int 494*0Sstevel@tonic-gate hs_mountfs( 495*0Sstevel@tonic-gate struct vfs *vfsp, 496*0Sstevel@tonic-gate dev_t dev, 497*0Sstevel@tonic-gate char *path, 498*0Sstevel@tonic-gate mode_t mode, 499*0Sstevel@tonic-gate int mount_flags, 500*0Sstevel@tonic-gate struct cred *cr, 501*0Sstevel@tonic-gate int isroot) 502*0Sstevel@tonic-gate { 503*0Sstevel@tonic-gate struct vnode *devvp; 504*0Sstevel@tonic-gate struct hsfs *tsp; 505*0Sstevel@tonic-gate struct hsfs *fsp = NULL; 506*0Sstevel@tonic-gate struct vattr vap; 507*0Sstevel@tonic-gate struct hsnode *hp; 508*0Sstevel@tonic-gate int error; 509*0Sstevel@tonic-gate struct timeval tv; 510*0Sstevel@tonic-gate int fsid; 511*0Sstevel@tonic-gate int use_rrip = (mount_flags & HSFSMNT_NORRIP) == 0; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate /* 514*0Sstevel@tonic-gate * Open the device 515*0Sstevel@tonic-gate */ 516*0Sstevel@tonic-gate devvp = makespecvp(dev, VBLK); 517*0Sstevel@tonic-gate ASSERT(devvp != 0); 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate /* 520*0Sstevel@tonic-gate * Open the target device (file) for read only. 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate if (error = VOP_OPEN(&devvp, FREAD, cr)) { 523*0Sstevel@tonic-gate VN_RELE(devvp); 524*0Sstevel@tonic-gate return (error); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate /* 528*0Sstevel@tonic-gate * Refuse to go any further if this 529*0Sstevel@tonic-gate * device is being used for swapping 530*0Sstevel@tonic-gate */ 531*0Sstevel@tonic-gate if (IS_SWAPVP(common_specvp(devvp))) { 532*0Sstevel@tonic-gate error = EBUSY; 533*0Sstevel@tonic-gate goto cleanup; 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate vap.va_mask = AT_SIZE; 537*0Sstevel@tonic-gate if ((error = VOP_GETATTR(devvp, &vap, ATTR_COMM, cr)) != 0) { 538*0Sstevel@tonic-gate cmn_err(CE_NOTE, "Cannot get attributes of the CD-ROM driver"); 539*0Sstevel@tonic-gate goto cleanup; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* 543*0Sstevel@tonic-gate * Make sure we have a nonzero size partition. 544*0Sstevel@tonic-gate * The current version of the SD driver will *not* fail the open 545*0Sstevel@tonic-gate * of such a partition so we have to check for it here. 546*0Sstevel@tonic-gate */ 547*0Sstevel@tonic-gate if (vap.va_size == 0) { 548*0Sstevel@tonic-gate error = ENXIO; 549*0Sstevel@tonic-gate goto cleanup; 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * Init a new hsfs structure. 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate fsp = kmem_zalloc(sizeof (*fsp), KM_SLEEP); 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate /* hardwire perms, uid, gid */ 558*0Sstevel@tonic-gate fsp->hsfs_vol.vol_uid = hsfs_default_uid; 559*0Sstevel@tonic-gate fsp->hsfs_vol.vol_gid = hsfs_default_gid; 560*0Sstevel@tonic-gate fsp->hsfs_vol.vol_prot = hsfs_default_mode; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate /* 563*0Sstevel@tonic-gate * Look for a Standard File Structure Volume Descriptor, 564*0Sstevel@tonic-gate * of which there must be at least one. 565*0Sstevel@tonic-gate * If found, check for volume size consistency. 566*0Sstevel@tonic-gate * 567*0Sstevel@tonic-gate * XXX - va_size may someday not be large enough to do this correctly. 568*0Sstevel@tonic-gate */ 569*0Sstevel@tonic-gate error = hs_findhsvol(fsp, devvp, &fsp->hsfs_vol); 570*0Sstevel@tonic-gate if (error == EINVAL) /* not in hs format, try iso 9660 format */ 571*0Sstevel@tonic-gate error = hs_findisovol(fsp, devvp, &fsp->hsfs_vol); 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate if (error) 574*0Sstevel@tonic-gate goto cleanup; 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * Generate a file system ID from the CD-ROM, 578*0Sstevel@tonic-gate * and check it for uniqueness. 579*0Sstevel@tonic-gate * 580*0Sstevel@tonic-gate * What we are aiming for is some chance of integrity 581*0Sstevel@tonic-gate * across disk change. That is, if a client has an fhandle, 582*0Sstevel@tonic-gate * it will be valid as long as the same disk is mounted. 583*0Sstevel@tonic-gate */ 584*0Sstevel@tonic-gate fsid = compute_cdrom_id(fsp, devvp); 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate mutex_enter(&hs_mounttab_lock); 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate if (fsid == 0 || fsid == -1) { 589*0Sstevel@tonic-gate uniqtime(&tv); 590*0Sstevel@tonic-gate fsid = tv.tv_sec; 591*0Sstevel@tonic-gate } else /* make sure that the fsid is unique */ 592*0Sstevel@tonic-gate for (tsp = hs_mounttab; tsp != NULL; tsp = tsp->hsfs_next) { 593*0Sstevel@tonic-gate if (fsid == tsp->hsfs_vfs->vfs_fsid.val[0]) { 594*0Sstevel@tonic-gate uniqtime(&tv); 595*0Sstevel@tonic-gate fsid = tv.tv_sec; 596*0Sstevel@tonic-gate break; 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate } 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate fsp->hsfs_next = hs_mounttab; 601*0Sstevel@tonic-gate hs_mounttab = fsp; 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate fsp->hsfs_devvp = devvp; 604*0Sstevel@tonic-gate fsp->hsfs_vfs = vfsp; 605*0Sstevel@tonic-gate fsp->hsfs_fsmnt = kmem_alloc(strlen(path) + 1, KM_SLEEP); 606*0Sstevel@tonic-gate (void) strcpy(fsp->hsfs_fsmnt, path); 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate mutex_init(&fsp->hsfs_free_lock, NULL, MUTEX_DEFAULT, NULL); 609*0Sstevel@tonic-gate rw_init(&fsp->hsfs_hash_lock, NULL, RW_DEFAULT, NULL); 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate vfsp->vfs_data = (caddr_t)fsp; 612*0Sstevel@tonic-gate vfsp->vfs_dev = dev; 613*0Sstevel@tonic-gate vfsp->vfs_fstype = hsfsfstype; 614*0Sstevel@tonic-gate vfsp->vfs_bsize = fsp->hsfs_vol.lbn_size; /* %% */ 615*0Sstevel@tonic-gate vfsp->vfs_fsid.val[0] = fsid; 616*0Sstevel@tonic-gate vfsp->vfs_fsid.val[1] = hsfsfstype; 617*0Sstevel@tonic-gate 618*0Sstevel@tonic-gate /* 619*0Sstevel@tonic-gate * If the root directory does not appear to be 620*0Sstevel@tonic-gate * valid, use what it points to as "." instead. 621*0Sstevel@tonic-gate * Some Defense Mapping Agency disks are non-conformant 622*0Sstevel@tonic-gate * in this way. 623*0Sstevel@tonic-gate */ 624*0Sstevel@tonic-gate if (!hsfs_valid_dir(&fsp->hsfs_vol.root_dir)) { 625*0Sstevel@tonic-gate hs_log_bogus_disk_warning(fsp, HSFS_ERR_BAD_ROOT_DIR, 0); 626*0Sstevel@tonic-gate if (hs_remakenode(fsp->hsfs_vol.root_dir.ext_lbn, 627*0Sstevel@tonic-gate (uint_t)0, vfsp, &fsp->hsfs_rootvp)) { 628*0Sstevel@tonic-gate error = EINVAL; 629*0Sstevel@tonic-gate goto cleanup; 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate } else { 632*0Sstevel@tonic-gate fsp->hsfs_rootvp = hs_makenode(&fsp->hsfs_vol.root_dir, 633*0Sstevel@tonic-gate fsp->hsfs_vol.root_dir.ext_lbn, 0, vfsp); 634*0Sstevel@tonic-gate } 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate /* mark vnode as VROOT */ 637*0Sstevel@tonic-gate fsp->hsfs_rootvp->v_flag |= VROOT; 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate /* Here we take care of some special case stuff for mountroot */ 640*0Sstevel@tonic-gate if (isroot) { 641*0Sstevel@tonic-gate fsp->hsfs_rootvp->v_rdev = devvp->v_rdev; 642*0Sstevel@tonic-gate rootvp = fsp->hsfs_rootvp; 643*0Sstevel@tonic-gate } 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate /* XXX - ignore the path table for now */ 646*0Sstevel@tonic-gate fsp->hsfs_ptbl = NULL; 647*0Sstevel@tonic-gate hp = VTOH(fsp->hsfs_rootvp); 648*0Sstevel@tonic-gate hp->hs_ptbl_idx = NULL; 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate if (use_rrip) 651*0Sstevel@tonic-gate hs_check_root_dirent(fsp->hsfs_rootvp, &(hp->hs_dirent)); 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate fsp->hsfs_namemax = IS_RRIP_IMPLEMENTED(fsp) 654*0Sstevel@tonic-gate ? RRIP_FILE_NAMELEN 655*0Sstevel@tonic-gate : ISO_FILE_NAMELEN; 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * if RRIP, don't copy NOMAPLCASE or NOTRAILDOT to hsfs_flags 658*0Sstevel@tonic-gate */ 659*0Sstevel@tonic-gate if (IS_RRIP_IMPLEMENTED(fsp)) 660*0Sstevel@tonic-gate mount_flags &= ~(HSFSMNT_NOMAPLCASE | HSFSMNT_NOTRAILDOT); 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate fsp->hsfs_flags = mount_flags; 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate /* set the magic word */ 665*0Sstevel@tonic-gate fsp->hsfs_magic = HSFS_MAGIC; 666*0Sstevel@tonic-gate mutex_exit(&hs_mounttab_lock); 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate return (0); 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate cleanup: 671*0Sstevel@tonic-gate (void) VOP_CLOSE(devvp, FREAD, 1, (offset_t)0, cr); 672*0Sstevel@tonic-gate VN_RELE(devvp); 673*0Sstevel@tonic-gate if (fsp) 674*0Sstevel@tonic-gate kmem_free(fsp, sizeof (*fsp)); 675*0Sstevel@tonic-gate return (error); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate /* 679*0Sstevel@tonic-gate * hs_findhsvol() 680*0Sstevel@tonic-gate * 681*0Sstevel@tonic-gate * Locate the Standard File Structure Volume Descriptor and 682*0Sstevel@tonic-gate * parse it into an hs_volume structure. 683*0Sstevel@tonic-gate * 684*0Sstevel@tonic-gate * XXX - May someday want to look for Coded Character Set FSVD, too. 685*0Sstevel@tonic-gate */ 686*0Sstevel@tonic-gate static int 687*0Sstevel@tonic-gate hs_findhsvol(struct hsfs *fsp, struct vnode *vp, struct hs_volume *hvp) 688*0Sstevel@tonic-gate { 689*0Sstevel@tonic-gate struct buf *secbp; 690*0Sstevel@tonic-gate int i; 691*0Sstevel@tonic-gate uchar_t *volp; 692*0Sstevel@tonic-gate int error; 693*0Sstevel@tonic-gate uint_t secno; 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate secno = hs_findvoldesc(vp->v_rdev, HS_VOLDESC_SEC); 696*0Sstevel@tonic-gate secbp = bread(vp->v_rdev, secno * 4, HS_SECTOR_SIZE); 697*0Sstevel@tonic-gate error = geterror(secbp); 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate if (error != 0) { 700*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hs_findhsvol: bread: error=(%d)", error); 701*0Sstevel@tonic-gate brelse(secbp); 702*0Sstevel@tonic-gate return (error); 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate volp = (uchar_t *)secbp->b_un.b_addr; 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate while (HSV_DESC_TYPE(volp) != VD_EOV) { 708*0Sstevel@tonic-gate for (i = 0; i < HSV_ID_STRLEN; i++) 709*0Sstevel@tonic-gate if (HSV_STD_ID(volp)[i] != HSV_ID_STRING[i]) 710*0Sstevel@tonic-gate goto cantfind; 711*0Sstevel@tonic-gate if (HSV_STD_VER(volp) != HSV_ID_VER) 712*0Sstevel@tonic-gate goto cantfind; 713*0Sstevel@tonic-gate switch (HSV_DESC_TYPE(volp)) { 714*0Sstevel@tonic-gate case VD_SFS: 715*0Sstevel@tonic-gate /* Standard File Structure */ 716*0Sstevel@tonic-gate fsp->hsfs_vol_type = HS_VOL_TYPE_HS; 717*0Sstevel@tonic-gate error = hs_parsehsvol(fsp, volp, hvp); 718*0Sstevel@tonic-gate brelse(secbp); 719*0Sstevel@tonic-gate return (error); 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate case VD_CCFS: 722*0Sstevel@tonic-gate /* Coded Character File Structure */ 723*0Sstevel@tonic-gate case VD_BOOT: 724*0Sstevel@tonic-gate case VD_UNSPEC: 725*0Sstevel@tonic-gate case VD_EOV: 726*0Sstevel@tonic-gate break; 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate brelse(secbp); 729*0Sstevel@tonic-gate ++secno; 730*0Sstevel@tonic-gate secbp = bread(vp->v_rdev, secno * 4, HS_SECTOR_SIZE); 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate error = geterror(secbp); 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate if (error != 0) { 735*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hs_findhsvol: bread: error=(%d)", 736*0Sstevel@tonic-gate error); 737*0Sstevel@tonic-gate brelse(secbp); 738*0Sstevel@tonic-gate return (error); 739*0Sstevel@tonic-gate } 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate volp = (uchar_t *)secbp->b_un.b_addr; 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate cantfind: 744*0Sstevel@tonic-gate brelse(secbp); 745*0Sstevel@tonic-gate return (EINVAL); 746*0Sstevel@tonic-gate } 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate /* 749*0Sstevel@tonic-gate * hs_parsehsvol 750*0Sstevel@tonic-gate * 751*0Sstevel@tonic-gate * Parse the Standard File Structure Volume Descriptor into 752*0Sstevel@tonic-gate * an hs_volume structure. We can't just bcopy it into the 753*0Sstevel@tonic-gate * structure because of byte-ordering problems. 754*0Sstevel@tonic-gate * 755*0Sstevel@tonic-gate */ 756*0Sstevel@tonic-gate static int 757*0Sstevel@tonic-gate hs_parsehsvol(struct hsfs *fsp, uchar_t *volp, struct hs_volume *hvp) 758*0Sstevel@tonic-gate { 759*0Sstevel@tonic-gate hvp->vol_size = HSV_VOL_SIZE(volp); 760*0Sstevel@tonic-gate hvp->lbn_size = HSV_BLK_SIZE(volp); 761*0Sstevel@tonic-gate if (hvp->lbn_size == 0) { 762*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hs_parsehsvol: logical block size in the " 763*0Sstevel@tonic-gate "SFSVD is zero"); 764*0Sstevel@tonic-gate return (EINVAL); 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate hvp->lbn_shift = ffs((long)hvp->lbn_size) - 1; 767*0Sstevel@tonic-gate hvp->lbn_secshift = ffs((long)howmany(HS_SECTOR_SIZE, 768*0Sstevel@tonic-gate (int)hvp->lbn_size)) - 1; 769*0Sstevel@tonic-gate hvp->lbn_maxoffset = hvp->lbn_size - 1; 770*0Sstevel@tonic-gate hs_parse_longdate(HSV_cre_date(volp), &hvp->cre_date); 771*0Sstevel@tonic-gate hs_parse_longdate(HSV_mod_date(volp), &hvp->mod_date); 772*0Sstevel@tonic-gate hvp->file_struct_ver = HSV_FILE_STRUCT_VER(volp); 773*0Sstevel@tonic-gate hvp->ptbl_len = HSV_PTBL_SIZE(volp); 774*0Sstevel@tonic-gate hvp->vol_set_size = (ushort_t)HSV_SET_SIZE(volp); 775*0Sstevel@tonic-gate hvp->vol_set_seq = (ushort_t)HSV_SET_SEQ(volp); 776*0Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN) 777*0Sstevel@tonic-gate hvp->ptbl_lbn = HSV_PTBL_MAN_LS(volp); 778*0Sstevel@tonic-gate #else 779*0Sstevel@tonic-gate hvp->ptbl_lbn = HSV_PTBL_MAN_MS(volp); 780*0Sstevel@tonic-gate #endif 781*0Sstevel@tonic-gate hs_copylabel(hvp, HSV_VOL_ID(volp)); 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate /* 784*0Sstevel@tonic-gate * Make sure that lbn_size is a power of two and otherwise valid. 785*0Sstevel@tonic-gate */ 786*0Sstevel@tonic-gate if (hvp->lbn_size & ~(1 << hvp->lbn_shift)) { 787*0Sstevel@tonic-gate cmn_err(CE_NOTE, 788*0Sstevel@tonic-gate "hsfs: %d-byte logical block size not supported", 789*0Sstevel@tonic-gate hvp->lbn_size); 790*0Sstevel@tonic-gate return (EINVAL); 791*0Sstevel@tonic-gate } 792*0Sstevel@tonic-gate return (hs_parsedir(fsp, HSV_ROOT_DIR(volp), &hvp->root_dir, 793*0Sstevel@tonic-gate (char *)NULL, (int *)NULL)); 794*0Sstevel@tonic-gate } 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate /* 797*0Sstevel@tonic-gate * hs_findisovol() 798*0Sstevel@tonic-gate * 799*0Sstevel@tonic-gate * Locate the Primary Volume Descriptor 800*0Sstevel@tonic-gate * parse it into an hs_volume structure. 801*0Sstevel@tonic-gate * 802*0Sstevel@tonic-gate * XXX - Supplementary, Partition not yet done 803*0Sstevel@tonic-gate */ 804*0Sstevel@tonic-gate static int 805*0Sstevel@tonic-gate hs_findisovol(struct hsfs *fsp, struct vnode *vp, 806*0Sstevel@tonic-gate struct hs_volume *hvp) 807*0Sstevel@tonic-gate { 808*0Sstevel@tonic-gate struct buf *secbp; 809*0Sstevel@tonic-gate int i; 810*0Sstevel@tonic-gate uchar_t *volp; 811*0Sstevel@tonic-gate int error; 812*0Sstevel@tonic-gate uint_t secno; 813*0Sstevel@tonic-gate int foundpvd = 0; 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate secno = hs_findvoldesc(vp->v_rdev, ISO_VOLDESC_SEC); 816*0Sstevel@tonic-gate secbp = bread(vp->v_rdev, secno * 4, ISO_SECTOR_SIZE); 817*0Sstevel@tonic-gate error = geterror(secbp); 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate if (error != 0) { 820*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hs_findisovol: bread: error=(%d)", error); 821*0Sstevel@tonic-gate brelse(secbp); 822*0Sstevel@tonic-gate return (error); 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate volp = (uchar_t *)secbp->b_un.b_addr; 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate while ((enum iso_voldesc_type) ISO_DESC_TYPE(volp) != ISO_VD_EOV) { 828*0Sstevel@tonic-gate for (i = 0; i < ISO_ID_STRLEN; i++) 829*0Sstevel@tonic-gate if (ISO_STD_ID(volp)[i] != ISO_ID_STRING[i]) 830*0Sstevel@tonic-gate goto cantfind; 831*0Sstevel@tonic-gate if (ISO_STD_VER(volp) != ISO_ID_VER) 832*0Sstevel@tonic-gate goto cantfind; 833*0Sstevel@tonic-gate switch (ISO_DESC_TYPE(volp)) { 834*0Sstevel@tonic-gate case ISO_VD_PVD: 835*0Sstevel@tonic-gate /* Standard File Structure */ 836*0Sstevel@tonic-gate if (foundpvd != 1) { 837*0Sstevel@tonic-gate fsp->hsfs_vol_type = HS_VOL_TYPE_ISO; 838*0Sstevel@tonic-gate if (error = hs_parseisovol(fsp, volp, hvp)) { 839*0Sstevel@tonic-gate brelse(secbp); 840*0Sstevel@tonic-gate return (error); 841*0Sstevel@tonic-gate } 842*0Sstevel@tonic-gate foundpvd = 1; 843*0Sstevel@tonic-gate } 844*0Sstevel@tonic-gate break; 845*0Sstevel@tonic-gate case ISO_VD_SVD: 846*0Sstevel@tonic-gate /* Supplementary Volume Descriptor */ 847*0Sstevel@tonic-gate break; 848*0Sstevel@tonic-gate case ISO_VD_BOOT: 849*0Sstevel@tonic-gate break; 850*0Sstevel@tonic-gate case ISO_VD_VPD: 851*0Sstevel@tonic-gate /* currently cannot handle partition */ 852*0Sstevel@tonic-gate break; 853*0Sstevel@tonic-gate case VD_EOV: 854*0Sstevel@tonic-gate break; 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate brelse(secbp); 857*0Sstevel@tonic-gate ++secno; 858*0Sstevel@tonic-gate secbp = bread(vp->v_rdev, secno * 4, HS_SECTOR_SIZE); 859*0Sstevel@tonic-gate error = geterror(secbp); 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate if (error != 0) { 862*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hs_findisovol: bread: error=(%d)", 863*0Sstevel@tonic-gate error); 864*0Sstevel@tonic-gate brelse(secbp); 865*0Sstevel@tonic-gate return (error); 866*0Sstevel@tonic-gate } 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate volp = (uchar_t *)secbp->b_un.b_addr; 869*0Sstevel@tonic-gate } 870*0Sstevel@tonic-gate if (foundpvd) { 871*0Sstevel@tonic-gate brelse(secbp); 872*0Sstevel@tonic-gate return (0); 873*0Sstevel@tonic-gate } 874*0Sstevel@tonic-gate cantfind: 875*0Sstevel@tonic-gate brelse(secbp); 876*0Sstevel@tonic-gate return (EINVAL); 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate /* 879*0Sstevel@tonic-gate * hs_parseisovol 880*0Sstevel@tonic-gate * 881*0Sstevel@tonic-gate * Parse the Primary Volume Descriptor into an hs_volume structure. 882*0Sstevel@tonic-gate * 883*0Sstevel@tonic-gate */ 884*0Sstevel@tonic-gate static int 885*0Sstevel@tonic-gate hs_parseisovol(struct hsfs *fsp, uchar_t *volp, struct hs_volume *hvp) 886*0Sstevel@tonic-gate { 887*0Sstevel@tonic-gate hvp->vol_size = ISO_VOL_SIZE(volp); 888*0Sstevel@tonic-gate hvp->lbn_size = ISO_BLK_SIZE(volp); 889*0Sstevel@tonic-gate if (hvp->lbn_size == 0) { 890*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hs_parseisovol: logical block size in the " 891*0Sstevel@tonic-gate "PVD is zero"); 892*0Sstevel@tonic-gate return (EINVAL); 893*0Sstevel@tonic-gate } 894*0Sstevel@tonic-gate hvp->lbn_shift = ffs((long)hvp->lbn_size) - 1; 895*0Sstevel@tonic-gate hvp->lbn_secshift = ffs((long)howmany(ISO_SECTOR_SIZE, 896*0Sstevel@tonic-gate (int)hvp->lbn_size)) - 1; 897*0Sstevel@tonic-gate hvp->lbn_maxoffset = hvp->lbn_size - 1; 898*0Sstevel@tonic-gate hs_parse_longdate(ISO_cre_date(volp), &hvp->cre_date); 899*0Sstevel@tonic-gate hs_parse_longdate(ISO_mod_date(volp), &hvp->mod_date); 900*0Sstevel@tonic-gate hvp->file_struct_ver = ISO_FILE_STRUCT_VER(volp); 901*0Sstevel@tonic-gate hvp->ptbl_len = ISO_PTBL_SIZE(volp); 902*0Sstevel@tonic-gate hvp->vol_set_size = (ushort_t)ISO_SET_SIZE(volp); 903*0Sstevel@tonic-gate hvp->vol_set_seq = (ushort_t)ISO_SET_SEQ(volp); 904*0Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN) 905*0Sstevel@tonic-gate hvp->ptbl_lbn = ISO_PTBL_MAN_LS(volp); 906*0Sstevel@tonic-gate #else 907*0Sstevel@tonic-gate hvp->ptbl_lbn = ISO_PTBL_MAN_MS(volp); 908*0Sstevel@tonic-gate #endif 909*0Sstevel@tonic-gate hs_copylabel(hvp, ISO_VOL_ID(volp)); 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate /* 912*0Sstevel@tonic-gate * Make sure that lbn_size is a power of two and otherwise valid. 913*0Sstevel@tonic-gate */ 914*0Sstevel@tonic-gate if (hvp->lbn_size & ~(1 << hvp->lbn_shift)) { 915*0Sstevel@tonic-gate cmn_err(CE_NOTE, 916*0Sstevel@tonic-gate "hsfs: %d-byte logical block size not supported", 917*0Sstevel@tonic-gate hvp->lbn_size); 918*0Sstevel@tonic-gate return (EINVAL); 919*0Sstevel@tonic-gate } 920*0Sstevel@tonic-gate return (hs_parsedir(fsp, ISO_ROOT_DIR(volp), &hvp->root_dir, 921*0Sstevel@tonic-gate (char *)NULL, (int *)NULL)); 922*0Sstevel@tonic-gate } 923*0Sstevel@tonic-gate 924*0Sstevel@tonic-gate /* 925*0Sstevel@tonic-gate * Common code for mount and umount. 926*0Sstevel@tonic-gate * Check that the user's argument is a reasonable 927*0Sstevel@tonic-gate * thing on which to mount, and return the device number if so. 928*0Sstevel@tonic-gate */ 929*0Sstevel@tonic-gate static int 930*0Sstevel@tonic-gate hs_getmdev(struct vfs *vfsp, char *fspec, int flags, dev_t *pdev, mode_t *mode, 931*0Sstevel@tonic-gate cred_t *cr) 932*0Sstevel@tonic-gate { 933*0Sstevel@tonic-gate int error; 934*0Sstevel@tonic-gate struct vnode *vp; 935*0Sstevel@tonic-gate struct vattr vap; 936*0Sstevel@tonic-gate dev_t dev; 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate /* 939*0Sstevel@tonic-gate * Get the device to be mounted 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate error = lookupname(fspec, (flags & MS_SYSSPACE) ? 942*0Sstevel@tonic-gate UIO_SYSSPACE : UIO_USERSPACE, FOLLOW, NULLVPP, &vp); 943*0Sstevel@tonic-gate if (error) { 944*0Sstevel@tonic-gate if (error == ENOENT) { 945*0Sstevel@tonic-gate return (ENODEV); /* needs translation */ 946*0Sstevel@tonic-gate } 947*0Sstevel@tonic-gate return (error); 948*0Sstevel@tonic-gate } 949*0Sstevel@tonic-gate if (vp->v_type != VBLK) { 950*0Sstevel@tonic-gate VN_RELE(vp); 951*0Sstevel@tonic-gate return (ENOTBLK); 952*0Sstevel@tonic-gate } 953*0Sstevel@tonic-gate /* 954*0Sstevel@tonic-gate * Can we read from the device? 955*0Sstevel@tonic-gate */ 956*0Sstevel@tonic-gate if ((error = VOP_ACCESS(vp, VREAD, 0, cr)) != 0 || 957*0Sstevel@tonic-gate (error = secpolicy_spec_open(cr, vp, FREAD)) != 0) { 958*0Sstevel@tonic-gate VN_RELE(vp); 959*0Sstevel@tonic-gate return (error); 960*0Sstevel@tonic-gate } 961*0Sstevel@tonic-gate 962*0Sstevel@tonic-gate vap.va_mask = AT_MODE; /* get protection mode */ 963*0Sstevel@tonic-gate (void) VOP_GETATTR(vp, &vap, 0, CRED()); 964*0Sstevel@tonic-gate *mode = vap.va_mode; 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate dev = *pdev = vp->v_rdev; 967*0Sstevel@tonic-gate VN_RELE(vp); 968*0Sstevel@tonic-gate 969*0Sstevel@tonic-gate /* 970*0Sstevel@tonic-gate * Ensure that this device isn't already mounted, 971*0Sstevel@tonic-gate * unless this is a REMOUNT request or we are told to suppress 972*0Sstevel@tonic-gate * mount checks. 973*0Sstevel@tonic-gate */ 974*0Sstevel@tonic-gate if ((flags & MS_NOCHECK) == 0) { 975*0Sstevel@tonic-gate if (vfs_devmounting(dev, vfsp)) 976*0Sstevel@tonic-gate return (EBUSY); 977*0Sstevel@tonic-gate if (vfs_devismounted(dev) && !(flags & MS_REMOUNT)) 978*0Sstevel@tonic-gate return (EBUSY); 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate if (getmajor(*pdev) >= devcnt) 982*0Sstevel@tonic-gate return (ENXIO); 983*0Sstevel@tonic-gate return (0); 984*0Sstevel@tonic-gate } 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate static void 987*0Sstevel@tonic-gate hs_copylabel(struct hs_volume *hvp, unsigned char *label) 988*0Sstevel@tonic-gate { 989*0Sstevel@tonic-gate /* cdrom volid is at most 32 bytes */ 990*0Sstevel@tonic-gate bcopy(label, hvp->vol_id, 32); 991*0Sstevel@tonic-gate hvp->vol_id[31] = NULL; 992*0Sstevel@tonic-gate } 993*0Sstevel@tonic-gate 994*0Sstevel@tonic-gate /* 995*0Sstevel@tonic-gate * Mount root file system. 996*0Sstevel@tonic-gate * "why" is ROOT_INIT on initial call, ROOT_REMOUNT if called to 997*0Sstevel@tonic-gate * remount the root file system, and ROOT_UNMOUNT if called to 998*0Sstevel@tonic-gate * unmount the root (e.g., as part of a system shutdown). 999*0Sstevel@tonic-gate * 1000*0Sstevel@tonic-gate * XXX - this may be partially machine-dependent; it, along with the VFS_SWAPVP 1001*0Sstevel@tonic-gate * operation, goes along with auto-configuration. A mechanism should be 1002*0Sstevel@tonic-gate * provided by which machine-INdependent code in the kernel can say "get me the 1003*0Sstevel@tonic-gate * right root file system" and "get me the right initial swap area", and have 1004*0Sstevel@tonic-gate * that done in what may well be a machine-dependent fashion. 1005*0Sstevel@tonic-gate * Unfortunately, it is also file-system-type dependent (NFS gets it via 1006*0Sstevel@tonic-gate * bootparams calls, UFS gets it from various and sundry machine-dependent 1007*0Sstevel@tonic-gate * mechanisms, as SPECFS does for swap). 1008*0Sstevel@tonic-gate */ 1009*0Sstevel@tonic-gate static int 1010*0Sstevel@tonic-gate hsfs_mountroot(struct vfs *vfsp, enum whymountroot why) 1011*0Sstevel@tonic-gate { 1012*0Sstevel@tonic-gate int error; 1013*0Sstevel@tonic-gate struct hsfs *fsp; 1014*0Sstevel@tonic-gate struct hs_volume *fvolp; 1015*0Sstevel@tonic-gate static int hsfsrootdone = 0; 1016*0Sstevel@tonic-gate dev_t rootdev; 1017*0Sstevel@tonic-gate mode_t mode = 0; 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate if (why == ROOT_INIT) { 1020*0Sstevel@tonic-gate if (hsfsrootdone++) 1021*0Sstevel@tonic-gate return (EBUSY); 1022*0Sstevel@tonic-gate rootdev = getrootdev(); 1023*0Sstevel@tonic-gate if (rootdev == (dev_t)NODEV) 1024*0Sstevel@tonic-gate return (ENODEV); 1025*0Sstevel@tonic-gate vfsp->vfs_dev = rootdev; 1026*0Sstevel@tonic-gate vfsp->vfs_flag |= VFS_RDONLY; 1027*0Sstevel@tonic-gate } else if (why == ROOT_REMOUNT) { 1028*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hsfs_mountroot: ROOT_REMOUNT"); 1029*0Sstevel@tonic-gate return (0); 1030*0Sstevel@tonic-gate } else if (why == ROOT_UNMOUNT) { 1031*0Sstevel@tonic-gate return (0); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate error = vfs_lock(vfsp); 1034*0Sstevel@tonic-gate if (error) { 1035*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hsfs_mountroot: couldn't get vfs_lock"); 1036*0Sstevel@tonic-gate return (error); 1037*0Sstevel@tonic-gate } 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate error = hs_mountfs(vfsp, rootdev, "/", mode, 1, CRED(), 1); 1040*0Sstevel@tonic-gate /* 1041*0Sstevel@tonic-gate * XXX - assumes root device is not indirect, because we don't set 1042*0Sstevel@tonic-gate * rootvp. Is rootvp used for anything? If so, make another arg 1043*0Sstevel@tonic-gate * to mountfs. 1044*0Sstevel@tonic-gate */ 1045*0Sstevel@tonic-gate if (error) { 1046*0Sstevel@tonic-gate vfs_unlock(vfsp); 1047*0Sstevel@tonic-gate if (rootvp) { 1048*0Sstevel@tonic-gate VN_RELE(rootvp); 1049*0Sstevel@tonic-gate rootvp = (struct vnode *)0; 1050*0Sstevel@tonic-gate } 1051*0Sstevel@tonic-gate return (error); 1052*0Sstevel@tonic-gate } 1053*0Sstevel@tonic-gate if (why == ROOT_INIT) 1054*0Sstevel@tonic-gate vfs_add((struct vnode *)0, vfsp, 1055*0Sstevel@tonic-gate (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0); 1056*0Sstevel@tonic-gate vfs_unlock(vfsp); 1057*0Sstevel@tonic-gate fsp = VFS_TO_HSFS(vfsp); 1058*0Sstevel@tonic-gate fvolp = &fsp->hsfs_vol; 1059*0Sstevel@tonic-gate #ifdef HSFS_CLKSET 1060*0Sstevel@tonic-gate if (fvolp->cre_date.tv_sec == 0) { 1061*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hsfs_mountroot: cre_date.tv_sec == 0"); 1062*0Sstevel@tonic-gate if (fvolp->mod_date.tv_sec == 0) { 1063*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hsfs_mountroot: mod_date.tv_sec == 0"); 1064*0Sstevel@tonic-gate cmn_err(CE_NOTE, "hsfs_mountroot: clkset(-1L)"); 1065*0Sstevel@tonic-gate clkset(-1L); 1066*0Sstevel@tonic-gate } else 1067*0Sstevel@tonic-gate clkset(fvolp->mod_date.tv_sec); 1068*0Sstevel@tonic-gate } else 1069*0Sstevel@tonic-gate clkset(fvolp->mod_date.tv_sec); 1070*0Sstevel@tonic-gate #else /* HSFS_CLKSET */ 1071*0Sstevel@tonic-gate clkset(-1L); 1072*0Sstevel@tonic-gate #endif /* HSFS_CLKSET */ 1073*0Sstevel@tonic-gate return (0); 1074*0Sstevel@tonic-gate } 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate /* 1077*0Sstevel@tonic-gate * hs_findvoldesc() 1078*0Sstevel@tonic-gate * 1079*0Sstevel@tonic-gate * Return the sector where the volume descriptor lives. This is 1080*0Sstevel@tonic-gate * a fixed value for "normal" cd-rom's, but can change for 1081*0Sstevel@tonic-gate * multisession cd's. 1082*0Sstevel@tonic-gate * 1083*0Sstevel@tonic-gate * desc_sec is the same for high-sierra and iso 9660 formats, why 1084*0Sstevel@tonic-gate * there are two differnt #defines used in the code for this is 1085*0Sstevel@tonic-gate * beyond me. These are standards, cast in concrete, right? 1086*0Sstevel@tonic-gate * To be general, however, this function supports passing in different 1087*0Sstevel@tonic-gate * values. 1088*0Sstevel@tonic-gate */ 1089*0Sstevel@tonic-gate static int 1090*0Sstevel@tonic-gate hs_findvoldesc(dev_t rdev, int desc_sec) 1091*0Sstevel@tonic-gate { 1092*0Sstevel@tonic-gate int secno; 1093*0Sstevel@tonic-gate int error; 1094*0Sstevel@tonic-gate int rval; /* ignored */ 1095*0Sstevel@tonic-gate 1096*0Sstevel@tonic-gate #ifdef CDROMREADOFFSET 1097*0Sstevel@tonic-gate /* 1098*0Sstevel@tonic-gate * Issue the Read Offset ioctl directly to the 1099*0Sstevel@tonic-gate * device. Ignore any errors and set starting 1100*0Sstevel@tonic-gate * secno to the default, otherwise add the 1101*0Sstevel@tonic-gate * VOLDESC sector number to the offset. 1102*0Sstevel@tonic-gate */ 1103*0Sstevel@tonic-gate error = cdev_ioctl(rdev, CDROMREADOFFSET, (intptr_t)&secno, 1104*0Sstevel@tonic-gate FNATIVE|FKIOCTL|FREAD, CRED(), &rval); 1105*0Sstevel@tonic-gate if (error) { 1106*0Sstevel@tonic-gate secno = desc_sec; 1107*0Sstevel@tonic-gate } else { 1108*0Sstevel@tonic-gate secno += desc_sec; 1109*0Sstevel@tonic-gate } 1110*0Sstevel@tonic-gate #else 1111*0Sstevel@tonic-gate secno = desc_sec; 1112*0Sstevel@tonic-gate #endif 1113*0Sstevel@tonic-gate 1114*0Sstevel@tonic-gate return (secno); 1115*0Sstevel@tonic-gate } 1116