Annotation of src/sys/fs/cd9660/cd9660_vfsops.c, Revision 1.31.2.3
1.31.2.3! yamt 1: /* $NetBSD: cd9660_vfsops.c,v 1.31.2.2 2006/08/11 15:45:33 yamt Exp $ */
1.1 jdolecek 2:
3: /*-
4: * Copyright (c) 1994
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley
8: * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
9: * Support code is derived from software contributed to Berkeley
10: * by Atsushi Murai (amurai@spec.co.jp).
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
1.9 agc 20: * 3. Neither the name of the University nor the names of its contributors
1.1 jdolecek 21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
37: */
38:
39: #include <sys/cdefs.h>
1.31.2.3! yamt 40: __KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.31.2.2 2006/08/11 15:45:33 yamt Exp $");
1.1 jdolecek 41:
42: #if defined(_KERNEL_OPT)
43: #include "opt_compat_netbsd.h"
44: #endif
45:
46: #include <sys/param.h>
1.10 atatat 47: #include <sys/sysctl.h>
1.1 jdolecek 48: #include <sys/systm.h>
49: #include <sys/namei.h>
50: #include <sys/proc.h>
51: #include <sys/kernel.h>
52: #include <sys/vnode.h>
53: #include <miscfs/specfs/specdev.h>
54: #include <sys/mount.h>
55: #include <sys/buf.h>
56: #include <sys/file.h>
57: #include <sys/disklabel.h>
58: #include <sys/device.h>
59: #include <sys/ioctl.h>
60: #include <sys/cdio.h>
61: #include <sys/errno.h>
62: #include <sys/malloc.h>
63: #include <sys/pool.h>
64: #include <sys/stat.h>
65: #include <sys/conf.h>
1.18 jdolecek 66: #include <sys/dirent.h>
1.31.2.1 yamt 67: #include <sys/kauth.h>
1.1 jdolecek 68:
69: #include <fs/cd9660/iso.h>
70: #include <fs/cd9660/cd9660_extern.h>
71: #include <fs/cd9660/iso_rrip.h>
72: #include <fs/cd9660/cd9660_node.h>
73: #include <fs/cd9660/cd9660_mount.h>
1.2 thorpej 74:
75: MALLOC_DEFINE(M_ISOFSMNT, "ISOFS mount", "ISOFS mount structure");
1.1 jdolecek 76:
77: extern const struct vnodeopv_desc cd9660_vnodeop_opv_desc;
78: extern const struct vnodeopv_desc cd9660_specop_opv_desc;
79: extern const struct vnodeopv_desc cd9660_fifoop_opv_desc;
80:
81: const struct vnodeopv_desc * const cd9660_vnodeopv_descs[] = {
82: &cd9660_vnodeop_opv_desc,
83: &cd9660_specop_opv_desc,
84: &cd9660_fifoop_opv_desc,
85: NULL,
86: };
87:
88: struct vfsops cd9660_vfsops = {
89: MOUNT_CD9660,
90: cd9660_mount,
91: cd9660_start,
92: cd9660_unmount,
93: cd9660_root,
94: cd9660_quotactl,
1.12 christos 95: cd9660_statvfs,
1.1 jdolecek 96: cd9660_sync,
97: cd9660_vget,
98: cd9660_fhtovp,
99: cd9660_vptofh,
100: cd9660_init,
101: cd9660_reinit,
102: cd9660_done,
103: cd9660_mountroot,
1.15 hannken 104: (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp,
1.20 thorpej 105: vfs_stdextattrctl,
1.1 jdolecek 106: cd9660_vnodeopv_descs,
1.31.2.3! yamt 107: 0, /* refcount */
! 108: { NULL, NULL } /* list */
1.1 jdolecek 109: };
1.23 thorpej 110: VFS_ATTACH(cd9660_vfsops);
1.1 jdolecek 111:
1.24 yamt 112: static const struct genfs_ops cd9660_genfsops = {
113: .gop_size = genfs_size,
1.1 jdolecek 114: };
115:
116: /*
117: * Called by vfs_mountroot when iso is going to be mounted as root.
118: *
119: * Name is updated by mount(8) after booting.
120: */
121: #define ROOTNAME "root_device"
122:
1.26 xtraeme 123: static int iso_makemp(struct iso_mnt *isomp, struct buf *bp, int *ea_len);
124: static int iso_mountfs(struct vnode *devvp, struct mount *mp,
1.30 christos 125: struct lwp *l, struct iso_args *argp);
1.1 jdolecek 126:
127: int
128: cd9660_mountroot()
129: {
130: struct mount *mp;
1.30 christos 131: struct lwp *l = curlwp; /* XXX */
1.1 jdolecek 132: int error;
133: struct iso_args args;
134:
1.31 thorpej 135: if (device_class(root_device) != DV_DISK)
1.1 jdolecek 136: return (ENODEV);
1.22 perry 137:
1.1 jdolecek 138: if ((error = vfs_rootmountalloc(MOUNT_CD9660, "root_device", &mp))
139: != 0) {
140: vrele(rootvp);
141: return (error);
142: }
143:
144: args.flags = ISOFSMNT_ROOT;
1.30 christos 145: if ((error = iso_mountfs(rootvp, mp, l, &args)) != 0) {
1.1 jdolecek 146: mp->mnt_op->vfs_refcount--;
147: vfs_unbusy(mp);
148: free(mp, M_MOUNT);
149: return (error);
150: }
151: simple_lock(&mountlist_slock);
152: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
153: simple_unlock(&mountlist_slock);
1.30 christos 154: (void)cd9660_statvfs(mp, &mp->mnt_stat, l);
1.1 jdolecek 155: vfs_unbusy(mp);
156: return (0);
157: }
158:
159: /*
160: * VFS Operations.
161: *
162: * mount system call
163: */
164: int
1.30 christos 165: cd9660_mount(mp, path, data, ndp, l)
1.1 jdolecek 166: struct mount *mp;
167: const char *path;
168: void *data;
169: struct nameidata *ndp;
1.30 christos 170: struct lwp *l;
1.1 jdolecek 171: {
172: struct vnode *devvp;
173: struct iso_args args;
174: int error;
1.28 dyoung 175: struct iso_mnt *imp = VFSTOISOFS(mp);
1.22 perry 176:
1.1 jdolecek 177: if (mp->mnt_flag & MNT_GETARGS) {
178: if (imp == NULL)
179: return EIO;
180: args.fspec = NULL;
181: args.flags = imp->im_flags;
182: return copyout(&args, data, sizeof(args));
183: }
1.3 dsl 184: error = copyin(data, &args, sizeof (struct iso_args));
1.1 jdolecek 185: if (error)
186: return (error);
1.22 perry 187:
1.1 jdolecek 188: if ((mp->mnt_flag & MNT_RDONLY) == 0)
189: return (EROFS);
1.22 perry 190:
1.27 jmmv 191: if ((mp->mnt_flag & MNT_UPDATE) && args.fspec == NULL)
192: return EINVAL;
193:
1.1 jdolecek 194: /*
195: * Not an update, or updating the name: look up the name
196: * and verify that it refers to a sensible block device.
197: */
1.30 christos 198: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, l);
1.1 jdolecek 199: if ((error = namei(ndp)) != 0)
200: return (error);
201: devvp = ndp->ni_vp;
202:
203: if (devvp->v_type != VBLK) {
204: vrele(devvp);
205: return ENOTBLK;
206: }
207: if (bdevsw_lookup(devvp->v_rdev) == NULL) {
208: vrele(devvp);
209: return ENXIO;
210: }
211: /*
212: * If mount by non-root, then verify that user has necessary
213: * permissions on the device.
214: */
1.31.2.2 yamt 215: if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL) != 0) {
1.1 jdolecek 216: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.31.2.2 yamt 217: error = VOP_ACCESS(devvp, VREAD, l->l_cred, l);
1.1 jdolecek 218: VOP_UNLOCK(devvp, 0);
219: if (error) {
220: vrele(devvp);
221: return (error);
222: }
223: }
1.21 mycroft 224: if ((mp->mnt_flag & MNT_UPDATE) == 0) {
225: /*
226: * Disallow multiple mounts of the same device.
227: * Disallow mounting of a device that is currently in use
228: * (except for root, which might share swap device for
229: * miniroot).
230: */
231: error = vfs_mountedon(devvp);
232: if (error)
233: goto fail;
234: if (vcount(devvp) > 1 && devvp != rootvp) {
235: error = EBUSY;
236: goto fail;
237: }
1.30 christos 238: error = VOP_OPEN(devvp, FREAD, FSCRED, l);
1.21 mycroft 239: if (error)
240: goto fail;
1.30 christos 241: error = iso_mountfs(devvp, mp, l, &args);
1.21 mycroft 242: if (error) {
243: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.30 christos 244: (void)VOP_CLOSE(devvp, FREAD, NOCRED, l);
1.21 mycroft 245: VOP_UNLOCK(devvp, 0);
246: goto fail;
247: }
248: } else {
249: vrele(devvp);
1.1 jdolecek 250: if (devvp != imp->im_devvp)
1.21 mycroft 251: return (EINVAL); /* needs translation */
1.1 jdolecek 252: }
1.12 christos 253: return set_statvfs_info(path, UIO_USERSPACE, args.fspec, UIO_USERSPACE,
1.30 christos 254: mp, l);
1.21 mycroft 255:
256: fail:
257: vrele(devvp);
258: return (error);
1.1 jdolecek 259: }
260:
261: /*
262: * Make a mount point from a volume descriptor
263: */
264: static int
265: iso_makemp(isomp, bp, ea_len)
266: struct iso_mnt *isomp;
267: struct buf *bp;
268: int *ea_len;
269: {
270: struct iso_primary_descriptor *pri;
271: int logical_block_size;
272: struct iso_directory_record *rootp;
273:
274: pri = (struct iso_primary_descriptor *)bp->b_data;
1.22 perry 275:
1.1 jdolecek 276: logical_block_size = isonum_723 (pri->logical_block_size);
1.22 perry 277:
1.1 jdolecek 278: if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
279: || (logical_block_size & (logical_block_size - 1)) != 0)
280: return -1;
1.22 perry 281:
1.1 jdolecek 282: rootp = (struct iso_directory_record *)pri->root_directory_record;
1.22 perry 283:
1.1 jdolecek 284: isomp->logical_block_size = logical_block_size;
285: isomp->volume_space_size = isonum_733 (pri->volume_space_size);
286: memcpy(isomp->root, rootp, sizeof(isomp->root));
287: isomp->root_extent = isonum_733 (rootp->extent);
288: isomp->root_size = isonum_733 (rootp->size);
289: isomp->im_joliet_level = 0;
1.22 perry 290:
1.1 jdolecek 291: isomp->im_bmask = logical_block_size - 1;
292: isomp->im_bshift = 0;
293: while ((1 << isomp->im_bshift) < isomp->logical_block_size)
294: isomp->im_bshift++;
295:
296: if (ea_len != NULL)
297: *ea_len = isonum_711(rootp->ext_attr_length);
298:
299: return 0;
300: }
301:
302: /*
303: * Common code for mount and mountroot
304: */
305: static int
1.30 christos 306: iso_mountfs(devvp, mp, l, argp)
1.1 jdolecek 307: struct vnode *devvp;
308: struct mount *mp;
1.30 christos 309: struct lwp *l;
1.1 jdolecek 310: struct iso_args *argp;
311: {
312: struct iso_mnt *isomp = (struct iso_mnt *)0;
313: struct buf *bp = NULL, *pribp = NULL, *supbp = NULL;
314: dev_t dev = devvp->v_rdev;
315: int error = EINVAL;
316: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
317: int iso_bsize;
318: int iso_blknum;
319: int joliet_level;
320: struct iso_volume_descriptor *vdp;
321: struct iso_supplementary_descriptor *sup;
322: int sess = 0;
323: int ext_attr_length;
324: struct disklabel label;
325:
326: if (!ronly)
327: return EROFS;
1.22 perry 328:
1.21 mycroft 329: /* Flush out any old buffers remaining from a previous use. */
1.31.2.2 yamt 330: if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
1.1 jdolecek 331: return (error);
1.22 perry 332:
1.1 jdolecek 333: /* This is the "logical sector size". The standard says this
334: * should be 2048 or the physical sector size on the device,
335: * whichever is greater. For now, we'll just use a constant.
336: */
337: iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
338:
1.30 christos 339: error = VOP_IOCTL(devvp, DIOCGDINFO, &label, FREAD, FSCRED, l);
1.1 jdolecek 340: if (!error &&
341: label.d_partitions[DISKPART(dev)].p_fstype == FS_ISO9660) {
342: /* XXX more sanity checks? */
343: sess = label.d_partitions[DISKPART(dev)].p_cdsession;
344: } else {
345: /* fallback to old method */
1.30 christos 346: error = VOP_IOCTL(devvp, CDIOREADMSADDR, &sess, 0, FSCRED, l);
1.1 jdolecek 347: if (error)
348: sess = 0; /* never mind */
349: }
1.4 christos 350: #ifdef ISO_DEBUG
1.1 jdolecek 351: printf("isofs: session offset (part %d) %d\n", DISKPART(dev), sess);
352: #endif
353:
354: for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
355: if ((error = bread(devvp, (iso_blknum+sess) * btodb(iso_bsize),
356: iso_bsize, NOCRED, &bp)) != 0)
357: goto out;
1.22 perry 358:
1.1 jdolecek 359: vdp = (struct iso_volume_descriptor *)bp->b_data;
360: if (memcmp(vdp->id, ISO_STANDARD_ID, sizeof(vdp->id)) != 0) {
361: error = EINVAL;
362: goto out;
363: }
364:
365: switch (isonum_711(vdp->type)) {
366: case ISO_VD_PRIMARY:
367: if (pribp == NULL) {
368: pribp = bp;
369: bp = NULL;
370: }
371: break;
372:
373: case ISO_VD_SUPPLEMENTARY:
374: if (supbp == NULL) {
375: supbp = bp;
376: bp = NULL;
377: }
378: break;
379:
380: default:
381: break;
382: }
383:
384: if (isonum_711 (vdp->type) == ISO_VD_END) {
385: brelse(bp);
386: bp = NULL;
387: break;
388: }
389:
390: if (bp != NULL) {
391: brelse(bp);
392: bp = NULL;
393: }
394: }
395:
396: if (pribp == NULL) {
397: error = EINVAL;
398: goto out;
399: }
400:
401: isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
1.3 dsl 402: memset(isomp, 0, sizeof *isomp);
1.1 jdolecek 403: if (iso_makemp(isomp, pribp, &ext_attr_length) == -1) {
404: error = EINVAL;
405: goto out;
406: }
407:
408: isomp->volume_space_size += sess;
409:
410: pribp->b_flags |= B_AGE;
411: brelse(pribp);
412: pribp = NULL;
1.22 perry 413:
1.1 jdolecek 414: mp->mnt_data = isomp;
1.12 christos 415: mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
416: mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_CD9660);
417: mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1.18 jdolecek 418: mp->mnt_stat.f_namemax = MAXNAMLEN;
1.1 jdolecek 419: mp->mnt_flag |= MNT_LOCAL;
420: mp->mnt_dev_bshift = iso_bsize;
421: mp->mnt_fs_bshift = isomp->im_bshift;
422: isomp->im_mountp = mp;
423: isomp->im_dev = dev;
424: isomp->im_devvp = devvp;
1.22 perry 425:
1.1 jdolecek 426: devvp->v_specmountpoint = mp;
1.22 perry 427:
1.1 jdolecek 428: /* Check the Rock Ridge Extension support */
429: if (!(argp->flags & ISOFSMNT_NORRIP)) {
430: struct iso_directory_record *rootp;
431:
432: if ((error = bread(isomp->im_devvp,
433: (isomp->root_extent + ext_attr_length) <<
434: (isomp->im_bshift - DEV_BSHIFT),
435: isomp->logical_block_size, NOCRED,
436: &bp)) != 0)
437: goto out;
1.22 perry 438:
1.1 jdolecek 439: rootp = (struct iso_directory_record *)bp->b_data;
1.22 perry 440:
1.1 jdolecek 441: if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
442: argp->flags |= ISOFSMNT_NORRIP;
443: } else {
444: argp->flags &= ~ISOFSMNT_GENS;
445: }
1.22 perry 446:
1.1 jdolecek 447: /*
448: * The contents are valid,
449: * but they will get reread as part of another vnode, so...
450: */
451: bp->b_flags |= B_AGE;
452: brelse(bp);
453: bp = NULL;
454: }
455: isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
456: ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_RRCASEINS);
457:
458: if (isomp->im_flags & ISOFSMNT_GENS)
459: isomp->iso_ftype = ISO_FTYPE_9660;
460: else if (isomp->im_flags & ISOFSMNT_NORRIP) {
461: isomp->iso_ftype = ISO_FTYPE_DEFAULT;
462: if (argp->flags & ISOFSMNT_NOCASETRANS)
463: isomp->im_flags |= ISOFSMNT_NOCASETRANS;
1.22 perry 464: } else
1.1 jdolecek 465: isomp->iso_ftype = ISO_FTYPE_RRIP;
466:
467: /* Check the Joliet Extension support */
468: if ((argp->flags & ISOFSMNT_NORRIP) != 0 &&
469: (argp->flags & ISOFSMNT_NOJOLIET) == 0 &&
470: supbp != NULL) {
471: joliet_level = 0;
472: sup = (struct iso_supplementary_descriptor *)supbp->b_data;
473:
474: if ((isonum_711(sup->flags) & 1) == 0) {
475: if (memcmp(sup->escape, "%/@", 3) == 0)
476: joliet_level = 1;
477: if (memcmp(sup->escape, "%/C", 3) == 0)
478: joliet_level = 2;
479: if (memcmp(sup->escape, "%/E", 3) == 0)
480: joliet_level = 3;
481: }
482: if (joliet_level != 0) {
483: if (iso_makemp(isomp, supbp, NULL) == -1) {
484: error = EINVAL;
485: goto out;
486: }
487: isomp->im_joliet_level = joliet_level;
488: }
489: }
490:
491: if (supbp != NULL) {
492: brelse(supbp);
493: supbp = NULL;
494: }
1.22 perry 495:
1.1 jdolecek 496: return 0;
497: out:
498: if (bp)
499: brelse(bp);
500: if (pribp)
501: brelse(pribp);
502: if (supbp)
503: brelse(supbp);
504: if (isomp) {
1.3 dsl 505: free(isomp, M_ISOFSMNT);
1.1 jdolecek 506: mp->mnt_data = NULL;
507: }
508: return error;
509: }
510:
511: /*
512: * Make a filesystem operational.
513: * Nothing to do at the moment.
514: */
515: /* ARGSUSED */
516: int
1.30 christos 517: cd9660_start(mp, flags, l)
1.1 jdolecek 518: struct mount *mp;
519: int flags;
1.30 christos 520: struct lwp *l;
1.1 jdolecek 521: {
522: return 0;
523: }
524:
525: /*
526: * unmount system call
527: */
528: int
1.30 christos 529: cd9660_unmount(mp, mntflags, l)
1.1 jdolecek 530: struct mount *mp;
531: int mntflags;
1.30 christos 532: struct lwp *l;
1.1 jdolecek 533: {
534: struct iso_mnt *isomp;
535: int error, flags = 0;
1.22 perry 536:
1.1 jdolecek 537: if (mntflags & MNT_FORCE)
538: flags |= FORCECLOSE;
539: #if 0
540: mntflushbuf(mp, 0);
541: if (mntinvalbuf(mp))
542: return EBUSY;
543: #endif
544: if ((error = vflush(mp, NULLVP, flags)) != 0)
545: return (error);
546:
547: isomp = VFSTOISOFS(mp);
548:
549: #ifdef ISODEVMAP
550: if (isomp->iso_ftype == ISO_FTYPE_RRIP)
551: iso_dunmap(isomp->im_dev);
552: #endif
553:
554: if (isomp->im_devvp->v_type != VBAD)
555: isomp->im_devvp->v_specmountpoint = NULL;
556:
557: vn_lock(isomp->im_devvp, LK_EXCLUSIVE | LK_RETRY);
1.30 christos 558: error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, l);
1.1 jdolecek 559: vput(isomp->im_devvp);
1.3 dsl 560: free(isomp, M_ISOFSMNT);
1.1 jdolecek 561: mp->mnt_data = NULL;
562: mp->mnt_flag &= ~MNT_LOCAL;
563: return (error);
564: }
565:
566: /*
567: * Return root of a filesystem
568: */
569: int
1.7 thorpej 570: cd9660_root(mp, vpp)
1.1 jdolecek 571: struct mount *mp;
572: struct vnode **vpp;
573: {
574: struct iso_mnt *imp = VFSTOISOFS(mp);
575: struct iso_directory_record *dp =
576: (struct iso_directory_record *)imp->root;
577: ino_t ino = isodirino(dp, imp);
1.22 perry 578:
1.1 jdolecek 579: /*
580: * With RRIP we must use the `.' entry of the root directory.
581: * Simply tell vget, that it's a relocated directory.
582: */
583: return (cd9660_vget_internal(mp, ino, vpp,
1.7 thorpej 584: imp->iso_ftype == ISO_FTYPE_RRIP, dp));
1.1 jdolecek 585: }
586:
587: /*
588: * Do operations associated with quotas, not supported
589: */
590: /* ARGSUSED */
591: int
1.30 christos 592: cd9660_quotactl(mp, cmd, uid, arg, l)
1.1 jdolecek 593: struct mount *mp;
594: int cmd;
595: uid_t uid;
1.13 jrf 596: void *arg;
1.30 christos 597: struct lwp *l;
1.1 jdolecek 598: {
599:
600: return (EOPNOTSUPP);
601: }
602:
603: /*
604: * Get file system statistics.
605: */
606: int
1.30 christos 607: cd9660_statvfs(mp, sbp, l)
1.1 jdolecek 608: struct mount *mp;
1.12 christos 609: struct statvfs *sbp;
1.30 christos 610: struct lwp *l;
1.1 jdolecek 611: {
612: struct iso_mnt *isomp;
1.22 perry 613:
1.1 jdolecek 614: isomp = VFSTOISOFS(mp);
615:
616: sbp->f_bsize = isomp->logical_block_size;
1.12 christos 617: sbp->f_frsize = sbp->f_bsize;
1.1 jdolecek 618: sbp->f_iosize = sbp->f_bsize; /* XXX */
619: sbp->f_blocks = isomp->volume_space_size;
620: sbp->f_bfree = 0; /* total free blocks */
621: sbp->f_bavail = 0; /* blocks free for non superuser */
1.12 christos 622: sbp->f_bresvd = 0; /* total reserved blocks */
1.1 jdolecek 623: sbp->f_files = 0; /* total files */
624: sbp->f_ffree = 0; /* free file nodes */
1.25 jmmv 625: sbp->f_favail = 0; /* free file nodes for non superuser */
1.12 christos 626: sbp->f_fresvd = 0; /* reserved file nodes */
627: copy_statvfs_info(sbp, mp);
1.1 jdolecek 628: /* Use the first spare for flags: */
629: sbp->f_spare[0] = isomp->im_flags;
630: return 0;
631: }
632:
633: /* ARGSUSED */
634: int
1.30 christos 635: cd9660_sync(mp, waitfor, cred, l)
1.1 jdolecek 636: struct mount *mp;
637: int waitfor;
1.31.2.1 yamt 638: kauth_cred_t cred;
1.30 christos 639: struct lwp *l;
1.1 jdolecek 640: {
641: return (0);
642: }
643:
644: /*
645: * File handle to vnode
646: *
647: * Have to be really careful about stale file handles:
648: * - check that the inode number is in range
649: * - call iget() to get the locked inode
650: * - check for an unallocated inode (i_mode == 0)
651: * - check that the generation number matches
652: */
653:
654: struct ifid {
655: ushort ifid_len;
656: ushort ifid_pad;
657: int ifid_ino;
658: long ifid_start;
659: };
660:
661: /* ARGSUSED */
662: int
1.7 thorpej 663: cd9660_fhtovp(mp, fhp, vpp)
1.1 jdolecek 664: struct mount *mp;
665: struct fid *fhp;
666: struct vnode **vpp;
667: {
1.31.2.2 yamt 668: struct ifid ifh;
1.1 jdolecek 669: struct iso_node *ip;
670: struct vnode *nvp;
671: int error;
1.22 perry 672:
1.31.2.2 yamt 673: if (fhp->fid_len != sizeof(ifh))
674: return EINVAL;
675:
676: memcpy(&ifh, fhp, sizeof(ifh));
1.1 jdolecek 677: #ifdef ISOFS_DBG
678: printf("fhtovp: ino %d, start %ld\n",
1.31.2.2 yamt 679: ifh.ifid_ino, ifh.ifid_start);
1.1 jdolecek 680: #endif
1.22 perry 681:
1.31.2.2 yamt 682: if ((error = VFS_VGET(mp, ifh.ifid_ino, &nvp)) != 0) {
1.1 jdolecek 683: *vpp = NULLVP;
684: return (error);
685: }
686: ip = VTOI(nvp);
687: if (ip->inode.iso_mode == 0) {
688: vput(nvp);
689: *vpp = NULLVP;
690: return (ESTALE);
691: }
692: *vpp = nvp;
693: return (0);
694: }
695:
696: int
1.7 thorpej 697: cd9660_vget(mp, ino, vpp)
1.1 jdolecek 698: struct mount *mp;
699: ino_t ino;
700: struct vnode **vpp;
701: {
702:
703: /*
704: * XXXX
705: * It would be nice if we didn't always set the `relocated' flag
706: * and force the extra read, but I don't want to think about fixing
707: * that right now.
708: */
709: return (cd9660_vget_internal(mp, ino, vpp,
710: #if 0
711: VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
712: #else
713: 0,
714: #endif
1.7 thorpej 715: NULL));
1.1 jdolecek 716: }
717:
718: int
1.7 thorpej 719: cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
1.1 jdolecek 720: struct mount *mp;
721: ino_t ino;
722: struct vnode **vpp;
723: int relocated;
724: struct iso_directory_record *isodir;
725: {
726: struct iso_mnt *imp;
727: struct iso_node *ip;
728: #ifdef ISODEVMAP
729: struct iso_dnode *dp;
730: #endif
731: struct buf *bp;
732: struct vnode *vp, *nvp;
733: dev_t dev;
734: int error;
735:
736: imp = VFSTOISOFS(mp);
737: dev = imp->im_dev;
1.7 thorpej 738: if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
1.1 jdolecek 739: return (0);
740:
741: /* Allocate a new vnode/iso_node. */
742: if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {
743: *vpp = NULLVP;
744: return (error);
745: }
746: ip = pool_get(&cd9660_node_pool, PR_WAITOK);
1.3 dsl 747: memset(ip, 0, sizeof(struct iso_node));
1.1 jdolecek 748: vp->v_data = ip;
749: ip->i_vnode = vp;
750: ip->i_dev = dev;
751: ip->i_number = ino;
752:
753: /*
754: * Put it onto its hash chain and lock it so that other requests for
755: * this inode will block if they arrive while we are sleeping waiting
756: * for old data structures to be purged or for the contents of the
757: * disk portion of this inode to be read.
758: */
759: cd9660_ihashins(ip);
760:
761: if (isodir == 0) {
762: int lbn, off;
763:
764: lbn = lblkno(imp, ino);
765: if (lbn >= imp->volume_space_size) {
766: vput(vp);
767: printf("fhtovp: lbn exceed volume space %d\n", lbn);
768: return (ESTALE);
769: }
1.22 perry 770:
1.1 jdolecek 771: off = blkoff(imp, ino);
772: if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
773: vput(vp);
774: printf("fhtovp: crosses block boundary %d\n",
775: off + ISO_DIRECTORY_RECORD_SIZE);
776: return (ESTALE);
777: }
1.22 perry 778:
1.1 jdolecek 779: error = bread(imp->im_devvp,
780: lbn << (imp->im_bshift - DEV_BSHIFT),
781: imp->logical_block_size, NOCRED, &bp);
782: if (error) {
783: vput(vp);
784: brelse(bp);
785: printf("fhtovp: bread error %d\n",error);
786: return (error);
787: }
788: isodir = (struct iso_directory_record *)(bp->b_data + off);
789:
790: if (off + isonum_711(isodir->length) >
791: imp->logical_block_size) {
792: vput(vp);
793: if (bp != 0)
794: brelse(bp);
795: printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
796: off +isonum_711(isodir->length), off,
797: isonum_711(isodir->length));
798: return (ESTALE);
799: }
1.22 perry 800:
1.1 jdolecek 801: #if 0
802: if (isonum_733(isodir->extent) +
803: isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
804: if (bp != 0)
805: brelse(bp);
806: printf("fhtovp: file start miss %d vs %d\n",
807: isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
808: ifhp->ifid_start);
809: return (ESTALE);
810: }
811: #endif
812: } else
813: bp = 0;
814:
815: ip->i_mnt = imp;
816: ip->i_devvp = imp->im_devvp;
817: VREF(ip->i_devvp);
818:
819: if (relocated) {
820: /*
821: * On relocated directories we must
822: * read the `.' entry out of a dir.
823: */
824: ip->iso_start = ino >> imp->im_bshift;
825: if (bp != 0)
826: brelse(bp);
1.29 yamt 827: if ((error = cd9660_blkatoff(vp, (off_t)0, NULL, &bp)) != 0) {
1.1 jdolecek 828: vput(vp);
829: return (error);
830: }
831: isodir = (struct iso_directory_record *)bp->b_data;
832: }
833:
834: ip->iso_extent = isonum_733(isodir->extent);
835: ip->i_size = isonum_733(isodir->size);
836: ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
1.22 perry 837:
1.1 jdolecek 838: /*
839: * Setup time stamp, attribute
840: */
841: vp->v_type = VNON;
842: switch (imp->iso_ftype) {
843: default: /* ISO_FTYPE_9660 */
844: {
845: struct buf *bp2;
846: int off;
847: if ((imp->im_flags & ISOFSMNT_EXTATT)
848: && (off = isonum_711(isodir->ext_attr_length)))
1.29 yamt 849: cd9660_blkatoff(vp, (off_t)-(off << imp->im_bshift),
850: NULL, &bp2);
1.1 jdolecek 851: else
852: bp2 = NULL;
853: cd9660_defattr(isodir, ip, bp2);
854: cd9660_deftstamp(isodir, ip, bp2);
855: if (bp2)
856: brelse(bp2);
857: break;
858: }
859: case ISO_FTYPE_RRIP:
860: cd9660_rrip_analyze(isodir, ip, imp);
861: break;
862: }
863:
864: if (bp != 0)
865: brelse(bp);
866:
867: /*
868: * Initialize the associated vnode
869: */
870: switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
871: case VFIFO:
872: vp->v_op = cd9660_fifoop_p;
873: break;
874: case VCHR:
875: case VBLK:
876: /*
877: * if device, look at device number table for translation
878: */
879: #ifdef ISODEVMAP
880: if ((dp = iso_dmap(dev, ino, 0)) != NULL)
881: ip->inode.iso_rdev = dp->d_dev;
882: #endif
883: vp->v_op = cd9660_specop_p;
884: if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
885: /*
886: * Discard unneeded vnode, but save its iso_node.
887: * Note that the lock is carried over in the iso_node
888: * to the replacement vnode.
889: */
890: nvp->v_data = vp->v_data;
891: vp->v_data = NULL;
892: VOP_UNLOCK(vp, 0);
893: vp->v_op = spec_vnodeop_p;
894: vrele(vp);
895: vgone(vp);
896: lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock);
897: /*
898: * Reinitialize aliased inode.
899: */
900: vp = nvp;
901: ip->i_vnode = vp;
902: }
903: break;
904: case VLNK:
905: case VNON:
906: case VSOCK:
907: case VDIR:
908: case VBAD:
909: break;
910: case VREG:
911: uvm_vnp_setsize(vp, ip->i_size);
912: break;
913: }
1.22 perry 914:
1.1 jdolecek 915: if (ip->iso_extent == imp->root_extent)
916: vp->v_flag |= VROOT;
917:
918: /*
919: * XXX need generation number?
920: */
1.22 perry 921:
1.1 jdolecek 922: genfs_node_init(vp, &cd9660_genfsops);
923: *vpp = vp;
924: return (0);
925: }
926:
927: /*
928: * Vnode pointer to File handle
929: */
930: /* ARGSUSED */
931: int
1.31.2.2 yamt 932: cd9660_vptofh(vp, fhp, fh_size)
1.1 jdolecek 933: struct vnode *vp;
934: struct fid *fhp;
1.31.2.2 yamt 935: size_t *fh_size;
1.1 jdolecek 936: {
937: struct iso_node *ip = VTOI(vp);
1.31.2.2 yamt 938: struct ifid ifh;
1.22 perry 939:
1.31.2.2 yamt 940: if (*fh_size < sizeof(struct ifid)) {
941: *fh_size = sizeof(struct ifid);
942: return E2BIG;
943: }
944: *fh_size = sizeof(struct ifid);
945:
946: memset(&ifh, 0, sizeof(ifh));
947: ifh.ifid_len = sizeof(struct ifid);
948: ifh.ifid_ino = ip->i_number;
949: ifh.ifid_start = ip->iso_start;
950: memcpy(fhp, &ifh, sizeof(ifh));
1.22 perry 951:
1.1 jdolecek 952: #ifdef ISOFS_DBG
953: printf("vptofh: ino %d, start %ld\n",
1.31.2.2 yamt 954: ifh.ifid_ino,ifh.ifid_start);
1.1 jdolecek 955: #endif
956: return 0;
957: }
958:
1.10 atatat 959: SYSCTL_SETUP(sysctl_vfs_cd9660_setup, "sysctl vfs.cd9660 subtree setup")
1.1 jdolecek 960: {
1.10 atatat 961:
1.11 atatat 962: sysctl_createv(clog, 0, NULL, NULL,
963: CTLFLAG_PERMANENT, CTLTYPE_NODE, "vfs", NULL,
1.10 atatat 964: NULL, 0, NULL, 0,
965: CTL_VFS, CTL_EOL);
1.11 atatat 966: sysctl_createv(clog, 0, NULL, NULL,
1.14 atatat 967: CTLFLAG_PERMANENT, CTLTYPE_NODE, "cd9660",
968: SYSCTL_DESCR("ISO-9660 file system"),
1.10 atatat 969: NULL, 0, NULL, 0,
970: CTL_VFS, 14, CTL_EOL);
1.19 jdolecek 971:
972: sysctl_createv(clog, 0, NULL, NULL,
973: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.22 perry 974: CTLTYPE_INT, "utf8_joliet",
1.19 jdolecek 975: SYSCTL_DESCR("Encode Joliet file names to UTF-8"),
976: NULL, 0, &cd9660_utf8_joliet, 0,
977: CTL_VFS, 14, CD9660_UTF8_JOLIET, CTL_EOL);
978:
1.1 jdolecek 979: }
CVSweb <webmaster@jp.NetBSD.org>