Annotation of src/sys/fs/cd9660/cd9660_vnops.c, Revision 1.12
1.12 ! perry 1: /* $NetBSD: cd9660_vnops.c,v 1.11 2005/01/09 16:42:44 chs 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.6 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_vnops.c 8.15 (Berkeley) 5/27/95
37: */
38:
39: #include <sys/cdefs.h>
1.12 ! perry 40: __KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.11 2005/01/09 16:42:44 chs Exp $");
1.1 jdolecek 41:
42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/namei.h>
45: #include <sys/resourcevar.h>
46: #include <sys/kernel.h>
47: #include <sys/file.h>
48: #include <sys/stat.h>
49: #include <sys/buf.h>
50: #include <sys/proc.h>
51: #include <sys/mount.h>
52: #include <sys/vnode.h>
53: #include <sys/malloc.h>
54: #include <sys/dirent.h>
55:
56: #include <miscfs/fifofs/fifo.h>
57: #include <miscfs/genfs/genfs.h>
58: #include <miscfs/specfs/specdev.h>
59:
60: #include <fs/cd9660/iso.h>
61: #include <fs/cd9660/cd9660_extern.h>
62: #include <fs/cd9660/cd9660_node.h>
63: #include <fs/cd9660/iso_rrip.h>
64: #include <fs/cd9660/cd9660_mount.h>
65:
66: /*
67: * Structure for reading directories
68: */
69: struct isoreaddir {
70: struct dirent saveent;
71: struct dirent assocent;
72: struct dirent current;
73: off_t saveoff;
74: off_t assocoff;
75: off_t curroff;
76: struct uio *uio;
77: off_t uio_off;
78: int eofflag;
79: off_t *cookies;
80: int ncookies;
81: };
82:
83: int iso_uiodir __P((struct isoreaddir *, struct dirent *, off_t));
84: int iso_shipdir __P((struct isoreaddir *));
85:
86: #if 0
87: /*
88: * Mknod vnode call
89: * Actually remap the device number
90: */
91: int
92: cd9660_mknod(ndp, vap, cred, p)
93: struct nameidata *ndp;
94: struct ucred *cred;
95: struct vattr *vap;
96: struct proc *p;
97: {
98: #ifndef ISODEVMAP
99: free(ndp->ni_pnbuf, M_NAMEI);
100: vput(ndp->ni_dvp);
101: vput(ndp->ni_vp);
102: return (EINVAL);
103: #else
104: struct vnode *vp;
105: struct iso_node *ip;
106: struct iso_dnode *dp;
107:
108: vp = ndp->ni_vp;
109: ip = VTOI(vp);
110:
111: if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
112: || vap->va_type != vp->v_type
113: || (vap->va_type != VCHR && vap->va_type != VBLK)) {
114: free(ndp->ni_pnbuf, M_NAMEI);
115: vput(ndp->ni_dvp);
116: vput(ndp->ni_vp);
117: return (EINVAL);
118: }
119:
120: dp = iso_dmap(ip->i_dev, ip->i_number, 1);
121: if (ip->inode.iso_rdev == vap->va_rdev ||
122: vap->va_rdev == (dev_t)VNOVAL) {
123: /* same as the unmapped one, delete the mapping */
124: LIST_REMOVE(dp, d_hash);
125: FREE(dp, M_CACHE);
126: } else
127: /* enter new mapping */
128: dp->d_dev = vap->va_rdev;
129:
130: /*
131: * Remove inode so that it will be reloaded by iget and
132: * checked to see if it is an alias of an existing entry
133: * in the inode cache.
134: */
135: vput(vp);
136: vp->v_type = VNON;
137: vgone(vp);
138: return (0);
139: #endif
140: }
141: #endif
142:
143: /*
144: * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
145: * The mode is shifted to select the owner/group/other fields. The
146: * super user is granted all permissions.
147: */
148: int
149: cd9660_access(v)
150: void *v;
151: {
152: struct vop_access_args /* {
153: struct vnode *a_vp;
154: int a_mode;
155: struct ucred *a_cred;
1.5 fvdl 156: struct proc *a_p;
1.1 jdolecek 157: } */ *ap = v;
158: struct vnode *vp = ap->a_vp;
159: struct iso_node *ip = VTOI(vp);
160:
161: /*
162: * Disallow write attempts unless the file is a socket,
163: * fifo, or a block or character device resident on the
164: * file system.
165: */
166: if (ap->a_mode & VWRITE) {
167: switch (vp->v_type) {
168: case VDIR:
169: case VLNK:
170: case VREG:
171: return (EROFS);
172: default:
173: break;
174: }
175: }
176:
177: return (vaccess(vp->v_type, ip->inode.iso_mode & ALLPERMS,
178: ip->inode.iso_uid, ip->inode.iso_gid, ap->a_mode, ap->a_cred));
179: }
180:
181: int
182: cd9660_getattr(v)
183: void *v;
184: {
185: struct vop_getattr_args /* {
186: struct vnode *a_vp;
187: struct vattr *a_vap;
188: struct ucred *a_cred;
1.5 fvdl 189: struct proc *a_p;
1.1 jdolecek 190: } */ *ap = v;
191: struct vnode *vp = ap->a_vp;
192: struct iso_node *ip = VTOI(vp);
193: struct vattr *vap = ap->a_vap;
194:
195: vap->va_fsid = ip->i_dev;
196: vap->va_fileid = ip->i_number;
197:
198: vap->va_mode = ip->inode.iso_mode & ALLPERMS;
199: vap->va_nlink = ip->inode.iso_links;
200: vap->va_uid = ip->inode.iso_uid;
201: vap->va_gid = ip->inode.iso_gid;
202: vap->va_atime = ip->inode.iso_atime;
203: vap->va_mtime = ip->inode.iso_mtime;
204: vap->va_ctime = ip->inode.iso_ctime;
205: vap->va_rdev = ip->inode.iso_rdev;
206:
207: vap->va_size = (u_quad_t) ip->i_size;
208: if (ip->i_size == 0 && vp->v_type == VLNK) {
209: struct vop_readlink_args rdlnk;
210: struct iovec aiov;
211: struct uio auio;
212: char *cp;
213:
214: MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
215: aiov.iov_base = cp;
216: aiov.iov_len = MAXPATHLEN;
217: auio.uio_iov = &aiov;
218: auio.uio_iovcnt = 1;
219: auio.uio_offset = 0;
220: auio.uio_rw = UIO_READ;
221: auio.uio_segflg = UIO_SYSSPACE;
1.10 skrll 222: auio.uio_procp = NULL;
1.1 jdolecek 223: auio.uio_resid = MAXPATHLEN;
224: rdlnk.a_uio = &auio;
225: rdlnk.a_vp = ap->a_vp;
226: rdlnk.a_cred = ap->a_cred;
227: if (cd9660_readlink(&rdlnk) == 0)
228: vap->va_size = MAXPATHLEN - auio.uio_resid;
229: FREE(cp, M_TEMP);
230: }
231: vap->va_flags = 0;
232: vap->va_gen = 1;
233: vap->va_blocksize = ip->i_mnt->logical_block_size;
234: vap->va_bytes = (u_quad_t) ip->i_size;
235: vap->va_type = vp->v_type;
236: return (0);
237: }
238:
239: /*
240: * Vnode op for reading.
241: */
242: int
243: cd9660_read(v)
244: void *v;
245: {
246: struct vop_read_args /* {
247: struct vnode *a_vp;
248: struct uio *a_uio;
249: int a_ioflag;
250: struct ucred *a_cred;
251: } */ *ap = v;
252: struct vnode *vp = ap->a_vp;
253: struct uio *uio = ap->a_uio;
254: struct iso_node *ip = VTOI(vp);
255: struct iso_mnt *imp;
256: struct buf *bp;
257: daddr_t lbn, rablock;
258: off_t diff;
259: int rasize, error = 0;
260: long size, n, on;
261:
262: if (uio->uio_resid == 0)
263: return (0);
264: if (uio->uio_offset < 0)
265: return (EINVAL);
266: if (uio->uio_offset >= ip->i_size)
267: return 0;
268: ip->i_flag |= IN_ACCESS;
269: imp = ip->i_mnt;
270:
271: if (vp->v_type == VREG) {
272: error = 0;
273: while (uio->uio_resid > 0) {
274: void *win;
1.11 chs 275: int flags;
1.1 jdolecek 276: vsize_t bytelen = MIN(ip->i_size - uio->uio_offset,
277: uio->uio_resid);
278:
279: if (bytelen == 0)
280: break;
281: win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
282: &bytelen, UBC_READ);
283: error = uiomove(win, bytelen, uio);
1.11 chs 284: flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;
285: ubc_release(win, flags);
1.1 jdolecek 286: if (error)
287: break;
288: }
289: goto out;
290: }
291:
292: do {
293: lbn = lblkno(imp, uio->uio_offset);
294: on = blkoff(imp, uio->uio_offset);
295: n = MIN(imp->logical_block_size - on, uio->uio_resid);
296: diff = (off_t)ip->i_size - uio->uio_offset;
297: if (diff <= 0)
298: return (0);
299: if (diff < n)
300: n = diff;
301: size = blksize(imp, ip, lbn);
302: rablock = lbn + 1;
303: if (lblktosize(imp, rablock) < ip->i_size) {
304: rasize = blksize(imp, ip, rablock);
305: error = breadn(vp, lbn, size, &rablock,
306: &rasize, 1, NOCRED, &bp);
307: } else {
308: error = bread(vp, lbn, size, NOCRED, &bp);
309: }
310: n = MIN(n, size - bp->b_resid);
311: if (error) {
312: brelse(bp);
313: return (error);
314: }
315:
316: error = uiomove(bp->b_data + on, (int)n, uio);
317: brelse(bp);
318: } while (error == 0 && uio->uio_resid > 0 && n != 0);
319:
320: out:
321: return (error);
322: }
323:
324: int
1.2 itojun 325: iso_uiodir(idp, dp, off)
1.1 jdolecek 326: struct isoreaddir *idp;
327: struct dirent *dp;
328: off_t off;
329: {
330: int error;
331:
332: dp->d_name[dp->d_namlen] = 0;
333: dp->d_reclen = DIRENT_SIZE(dp);
334:
335: if (idp->uio->uio_resid < dp->d_reclen) {
336: idp->eofflag = 0;
337: return (-1);
338: }
339:
340: if (idp->cookies) {
341: if (idp->ncookies <= 0) {
342: idp->eofflag = 0;
343: return (-1);
344: }
345:
346: *idp->cookies++ = off;
347: --idp->ncookies;
348: }
349:
1.9 jrf 350: if ((error = uiomove(dp, dp->d_reclen, idp->uio)) != 0)
1.1 jdolecek 351: return (error);
352: idp->uio_off = off;
353: return (0);
354: }
355:
356: int
357: iso_shipdir(idp)
358: struct isoreaddir *idp;
359: {
360: struct dirent *dp;
361: int cl, sl, assoc;
362: int error;
363: char *cname, *sname;
364:
365: cl = idp->current.d_namlen;
366: cname = idp->current.d_name;
367:
368: if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
369: cl--;
370: cname++;
371: }
372:
373: dp = &idp->saveent;
374: sname = dp->d_name;
375: if (!(sl = dp->d_namlen)) {
376: dp = &idp->assocent;
377: sname = dp->d_name + 1;
378: sl = dp->d_namlen - 1;
379: }
380: if (sl > 0) {
381: if (sl != cl
382: || memcmp(sname, cname, sl)) {
383: if (idp->assocent.d_namlen) {
384: error = iso_uiodir(idp, &idp->assocent,
385: idp->assocoff);
386: if (error)
387: return (error);
388: idp->assocent.d_namlen = 0;
389: }
390: if (idp->saveent.d_namlen) {
391: error = iso_uiodir(idp, &idp->saveent,
392: idp->saveoff);
393: if (error)
394: return (error);
395: idp->saveent.d_namlen = 0;
396: }
397: }
398: }
399: idp->current.d_reclen = DIRENT_SIZE(&idp->current);
400: if (assoc) {
401: idp->assocoff = idp->curroff;
402: memcpy(&idp->assocent, &idp->current, idp->current.d_reclen);
403: } else {
404: idp->saveoff = idp->curroff;
405: memcpy(&idp->saveent, &idp->current, idp->current.d_reclen);
406: }
407: return (0);
408: }
409:
410: /*
411: * Vnode op for readdir
412: */
413: int
414: cd9660_readdir(v)
415: void *v;
416: {
417: struct vop_readdir_args /* {
418: struct vnode *a_vp;
419: struct uio *a_uio;
420: struct ucred *a_cred;
421: int *a_eofflag;
422: off_t **a_cookies;
423: int *a_ncookies;
424: } */ *ap = v;
425: struct uio *uio = ap->a_uio;
426: struct isoreaddir *idp;
427: struct vnode *vdp = ap->a_vp;
428: struct iso_node *dp;
429: struct iso_mnt *imp;
430: struct buf *bp = NULL;
431: struct iso_directory_record *ep;
432: int entryoffsetinblock;
433: doff_t endsearch;
434: u_long bmask;
435: int error = 0;
436: int reclen;
437: u_short namelen;
438: off_t *cookies = NULL;
439: int ncookies = 0;
440:
441: if (vdp->v_type != VDIR)
442: return (ENOTDIR);
443:
444: dp = VTOI(vdp);
445: imp = dp->i_mnt;
446: bmask = imp->im_bmask;
447:
448: MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
449: idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
450: /*
451: * XXX
452: * Is it worth trying to figure out the type?
453: */
454: idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
455: DT_UNKNOWN;
456: idp->uio = uio;
457: if (ap->a_ncookies == NULL)
458: idp->cookies = NULL;
459: else {
460: ncookies = uio->uio_resid / 16;
461: cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK);
462: idp->cookies = cookies;
463: idp->ncookies = ncookies;
464: }
465: idp->eofflag = 1;
466: idp->curroff = uio->uio_offset;
467:
468: if ((entryoffsetinblock = idp->curroff & bmask) &&
469: (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
470: FREE(idp, M_TEMP);
471: return (error);
472: }
473: endsearch = dp->i_size;
474:
475: while (idp->curroff < endsearch) {
476: /*
477: * If offset is on a block boundary,
478: * read the next directory block.
479: * Release previous if it exists.
480: */
481: if ((idp->curroff & bmask) == 0) {
482: if (bp != NULL)
483: brelse(bp);
484: error = VOP_BLKATOFF(vdp, (off_t)idp->curroff,
485: NULL, &bp);
486: if (error)
487: break;
488: entryoffsetinblock = 0;
489: }
490: /*
491: * Get pointer to next entry.
492: */
493: ep = (struct iso_directory_record *)
494: ((char *)bp->b_data + entryoffsetinblock);
495:
496: reclen = isonum_711(ep->length);
497: if (reclen == 0) {
498: /* skip to next block, if any */
499: idp->curroff =
500: (idp->curroff & ~bmask) + imp->logical_block_size;
501: continue;
502: }
503:
504: if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
505: error = EINVAL;
506: /* illegal entry, stop */
507: break;
508: }
509:
510: if (entryoffsetinblock + reclen > imp->logical_block_size) {
511: error = EINVAL;
512: /* illegal directory, so stop looking */
513: break;
514: }
515:
516: idp->current.d_namlen = isonum_711(ep->name_len);
517:
518: if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
519: error = EINVAL;
520: /* illegal entry, stop */
521: break;
522: }
523:
524: if (isonum_711(ep->flags)&2)
525: idp->current.d_fileno = isodirino(ep, imp);
526: else
527: idp->current.d_fileno = dbtob(bp->b_blkno) +
528: entryoffsetinblock;
529:
530: idp->curroff += reclen;
531:
532: switch (imp->iso_ftype) {
533: case ISO_FTYPE_RRIP:
1.2 itojun 534: cd9660_rrip_getname(ep, idp->current.d_name, &namelen,
535: &idp->current.d_fileno, imp);
1.1 jdolecek 536: idp->current.d_namlen = (u_char)namelen;
537: if (idp->current.d_namlen)
1.2 itojun 538: error = iso_uiodir(idp, &idp->current,
539: idp->curroff);
1.1 jdolecek 540: break;
541: default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
1.2 itojun 542: isofntrans(ep->name, idp->current.d_namlen,
1.1 jdolecek 543: idp->current.d_name, &namelen,
544: imp->iso_ftype == ISO_FTYPE_9660,
545: (imp->im_flags & ISOFSMNT_NOCASETRANS) == 0,
546: isonum_711(ep->flags)&4,
547: imp->im_joliet_level);
548: switch (idp->current.d_name[0]) {
549: case 0:
550: idp->current.d_name[0] = '.';
551: idp->current.d_namlen = 1;
1.2 itojun 552: error = iso_uiodir(idp, &idp->current,
553: idp->curroff);
1.1 jdolecek 554: break;
555: case 1:
1.2 itojun 556: strlcpy(idp->current.d_name, "..",
557: sizeof(idp->current.d_name));
1.1 jdolecek 558: idp->current.d_namlen = 2;
1.2 itojun 559: error = iso_uiodir(idp, &idp->current,
560: idp->curroff);
1.1 jdolecek 561: break;
562: default:
563: idp->current.d_namlen = (u_char)namelen;
564: if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
565: error = iso_shipdir(idp);
566: else
1.2 itojun 567: error = iso_uiodir(idp, &idp->current,
568: idp->curroff);
1.1 jdolecek 569: break;
570: }
571: }
572: if (error)
573: break;
574:
575: entryoffsetinblock += reclen;
576: }
577:
578: if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
579: idp->current.d_namlen = 0;
580: error = iso_shipdir(idp);
581: }
582: if (error < 0)
583: error = 0;
584:
585: if (ap->a_ncookies != NULL) {
586: if (error)
587: free(cookies, M_TEMP);
588: else {
589: /*
590: * Work out the number of cookies actually used.
591: */
592: *ap->a_ncookies = ncookies - idp->ncookies;
593: *ap->a_cookies = cookies;
594: }
595: }
596:
597: if (bp)
598: brelse (bp);
599:
600: uio->uio_offset = idp->uio_off;
601: *ap->a_eofflag = idp->eofflag;
602:
603: FREE(idp, M_TEMP);
604:
605: return (error);
606: }
607:
608: /*
609: * Return target name of a symbolic link
610: * Shouldn't we get the parent vnode and read the data from there?
611: * This could eventually result in deadlocks in cd9660_lookup.
612: * But otherwise the block read here is in the block buffer two times.
613: */
614: typedef struct iso_directory_record ISODIR;
615: typedef struct iso_node ISONODE;
616: typedef struct iso_mnt ISOMNT;
617: int
618: cd9660_readlink(v)
619: void *v;
620: {
621: struct vop_readlink_args /* {
622: struct vnode *a_vp;
623: struct uio *a_uio;
624: struct ucred *a_cred;
625: } */ *ap = v;
626: ISONODE *ip;
627: ISODIR *dirp;
628: ISOMNT *imp;
629: struct buf *bp;
630: struct uio *uio;
631: u_short symlen;
632: int error;
633: char *symname;
634:
635: ip = VTOI(ap->a_vp);
636: imp = ip->i_mnt;
637: uio = ap->a_uio;
638:
639: if (imp->iso_ftype != ISO_FTYPE_RRIP)
640: return (EINVAL);
641:
642: /*
643: * Get parents directory record block that this inode included.
644: */
645: error = bread(imp->im_devvp,
646: (ip->i_number >> imp->im_bshift) <<
647: (imp->im_bshift - DEV_BSHIFT),
648: imp->logical_block_size, NOCRED, &bp);
649: if (error) {
650: brelse(bp);
651: return (EINVAL);
652: }
653:
654: /*
655: * Setup the directory pointer for this inode
656: */
657: dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
658:
659: /*
660: * Just make sure, we have a right one....
661: * 1: Check not cross boundary on block
662: */
663: if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
664: > imp->logical_block_size) {
665: brelse(bp);
666: return (EINVAL);
667: }
668:
669: /*
670: * Now get a buffer
671: * Abuse a namei buffer for now.
672: */
1.3 reinoud 673: if (uio->uio_segflg == UIO_SYSSPACE &&
1.2 itojun 674: uio->uio_iov->iov_len >= MAXPATHLEN)
1.1 jdolecek 675: symname = uio->uio_iov->iov_base;
676: else
677: MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1.12 ! perry 678:
1.1 jdolecek 679: /*
680: * Ok, we just gathering a symbolic name in SL record.
681: */
682: if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
1.2 itojun 683: if (uio->uio_segflg != UIO_SYSSPACE ||
684: uio->uio_iov->iov_len < MAXPATHLEN)
1.1 jdolecek 685: FREE(symname, M_NAMEI);
686: brelse(bp);
687: return (EINVAL);
688: }
689: /*
690: * Don't forget before you leave from home ;-)
691: */
692: brelse(bp);
693:
694: /*
695: * return with the symbolic name to caller's.
696: */
1.2 itojun 697: if (uio->uio_segflg != UIO_SYSSPACE ||
698: uio->uio_iov->iov_len < MAXPATHLEN) {
1.1 jdolecek 699: error = uiomove(symname, symlen, uio);
700: FREE(symname, M_NAMEI);
701: return (error);
702: }
703: uio->uio_resid -= symlen;
704: uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen;
705: uio->uio_iov->iov_len -= symlen;
706: return (0);
707: }
708:
709: int
710: cd9660_link(v)
711: void *v;
712: {
713: struct vop_link_args /* {
714: struct vnode *a_dvp;
715: struct vnode *a_vp;
716: struct componentname *a_cnp;
717: } */ *ap = v;
718:
719: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
720: vput(ap->a_dvp);
721: return (EROFS);
722: }
723:
724: int
725: cd9660_symlink(v)
726: void *v;
727: {
728: struct vop_symlink_args /* {
729: struct vnode *a_dvp;
730: struct vnode **a_vpp;
731: struct componentname *a_cnp;
732: struct vattr *a_vap;
733: char *a_target;
734: } */ *ap = v;
735:
736: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
737: vput(ap->a_dvp);
738: return (EROFS);
739: }
740:
741: /*
742: * Calculate the logical to physical mapping if not done already,
743: * then call the device strategy routine.
744: */
745: int
746: cd9660_strategy(v)
747: void *v;
748: {
749: struct vop_strategy_args /* {
1.8 hannken 750: struct vnode *a_vp;
1.1 jdolecek 751: struct buf *a_bp;
752: } */ *ap = v;
753: struct buf *bp = ap->a_bp;
1.8 hannken 754: struct vnode *vp = ap->a_vp;
1.1 jdolecek 755: struct iso_node *ip;
756: int error;
757:
758: ip = VTOI(vp);
759: if (vp->v_type == VBLK || vp->v_type == VCHR)
760: panic("cd9660_strategy: spec");
761: if (bp->b_blkno == bp->b_lblkno) {
762: error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
763: if (error) {
764: bp->b_error = error;
765: bp->b_flags |= B_ERROR;
766: biodone(bp);
767: return (error);
768: }
769: if ((long)bp->b_blkno == -1)
770: clrbuf(bp);
771: }
772: if ((long)bp->b_blkno == -1) {
773: biodone(bp);
774: return (0);
775: }
776: vp = ip->i_devvp;
1.7 hannken 777: return (VOP_STRATEGY(vp, bp));
1.1 jdolecek 778: }
779:
780: /*
781: * Print out the contents of an inode.
782: */
783: /*ARGSUSED*/
784: int
785: cd9660_print(v)
786: void *v;
787: {
788:
789: printf("tag VT_ISOFS, isofs vnode\n");
790: return (0);
791: }
792:
793: /*
794: * Return POSIX pathconf information applicable to cd9660 filesystems.
795: */
796: int
797: cd9660_pathconf(v)
798: void *v;
799: {
800: struct vop_pathconf_args /* {
801: struct vnode *a_vp;
802: int a_name;
803: register_t *a_retval;
804: } */ *ap = v;
805: switch (ap->a_name) {
806: case _PC_LINK_MAX:
807: *ap->a_retval = 1;
808: return (0);
809: case _PC_NAME_MAX:
810: if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
811: *ap->a_retval = NAME_MAX;
812: else
813: *ap->a_retval = 37;
814: return (0);
815: case _PC_PATH_MAX:
816: *ap->a_retval = PATH_MAX;
817: return (0);
818: case _PC_PIPE_BUF:
819: *ap->a_retval = PIPE_BUF;
820: return (0);
821: case _PC_CHOWN_RESTRICTED:
822: *ap->a_retval = 1;
823: return (0);
824: case _PC_NO_TRUNC:
825: *ap->a_retval = 1;
826: return (0);
827: case _PC_SYNC_IO:
828: *ap->a_retval = 1;
829: return (0);
830: case _PC_FILESIZEBITS:
831: *ap->a_retval = 32;
832: return (0);
833: default:
834: return (EINVAL);
835: }
836: /* NOTREACHED */
837: }
838:
839: /*
840: * Allow changing the size for special files (and fifos).
841: */
842: int
843: cd9660_setattr(v)
844: void *v;
845: {
846: struct vop_setattr_args /* {
847: struct vnodeop_desc *a_desc;
848: struct vnode *a_vp;
849: struct vattr *a_vap;
850: struct ucred *a_cred;
1.5 fvdl 851: struct proc *a_p;
1.1 jdolecek 852: } */ *ap = v;
853: struct vattr *vap = ap->a_vap;
854: struct vnode *vp = ap->a_vp;
1.12 ! perry 855:
1.1 jdolecek 856: /*
857: * Only size is changeable.
858: */
859: if (vap->va_type != VNON
860: || vap->va_nlink != (nlink_t)VNOVAL
861: || vap->va_fsid != VNOVAL
862: || vap->va_fileid != VNOVAL
863: || vap->va_blocksize != VNOVAL
864: || vap->va_rdev != (dev_t)VNOVAL
865: || (int)vap->va_bytes != VNOVAL
866: || vap->va_gen != VNOVAL
867: || vap->va_flags != VNOVAL
868: || vap->va_uid != (uid_t)VNOVAL
869: || vap->va_gid != (gid_t)VNOVAL
870: || vap->va_atime.tv_sec != VNOVAL
871: || vap->va_mtime.tv_sec != VNOVAL
872: || vap->va_mode != (mode_t)VNOVAL)
873: return EOPNOTSUPP;
1.12 ! perry 874:
1.1 jdolecek 875: if (vap->va_size != VNOVAL
876: && vp->v_type != VCHR
877: && vp->v_type != VBLK
878: && vp->v_type != VFIFO
879: )
880: return EOPNOTSUPP;
1.12 ! perry 881:
1.5 fvdl 882: return VOP_TRUNCATE(vp, vap->va_size, 0, ap->a_cred, ap->a_p);
1.1 jdolecek 883: }
884:
885: /*
886: * Global vfs data structures for isofs
887: */
888: #define cd9660_create genfs_eopnotsupp
889: #define cd9660_mknod genfs_eopnotsupp
890: #define cd9660_write genfs_eopnotsupp
891: #define cd9660_lease_check genfs_lease_check
892: #define cd9660_fsync genfs_nullop
893: #define cd9660_remove genfs_eopnotsupp
894: #define cd9660_rename genfs_eopnotsupp
895: #define cd9660_mkdir genfs_eopnotsupp
896: #define cd9660_rmdir genfs_eopnotsupp
897: #define cd9660_advlock genfs_einval
898: #define cd9660_valloc genfs_eopnotsupp
899: #define cd9660_vfree genfs_nullop
900: #define cd9660_truncate genfs_eopnotsupp
901: #define cd9660_update genfs_nullop
902: #define cd9660_bwrite genfs_eopnotsupp
903: #define cd9660_revoke genfs_revoke
904:
905: /*
906: * Global vfs data structures for cd9660
907: */
908: int (**cd9660_vnodeop_p) __P((void *));
909: const struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
910: { &vop_default_desc, vn_default_error },
911: { &vop_lookup_desc, cd9660_lookup }, /* lookup */
912: { &vop_create_desc, cd9660_create }, /* create */
913: { &vop_mknod_desc, cd9660_mknod }, /* mknod */
914: { &vop_open_desc, cd9660_open }, /* open */
915: { &vop_close_desc, cd9660_close }, /* close */
916: { &vop_access_desc, cd9660_access }, /* access */
917: { &vop_getattr_desc, cd9660_getattr }, /* getattr */
918: { &vop_setattr_desc, cd9660_setattr }, /* setattr */
919: { &vop_read_desc, cd9660_read }, /* read */
920: { &vop_write_desc, cd9660_write }, /* write */
921: { &vop_lease_desc, cd9660_lease_check }, /* lease */
922: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
923: { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */
924: { &vop_poll_desc, cd9660_poll }, /* poll */
925: { &vop_revoke_desc, cd9660_revoke }, /* revoke */
926: { &vop_mmap_desc, cd9660_mmap }, /* mmap */
927: { &vop_fsync_desc, cd9660_fsync }, /* fsync */
928: { &vop_seek_desc, cd9660_seek }, /* seek */
929: { &vop_remove_desc, cd9660_remove }, /* remove */
930: { &vop_link_desc, cd9660_link }, /* link */
931: { &vop_rename_desc, cd9660_rename }, /* rename */
932: { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */
933: { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */
934: { &vop_symlink_desc, cd9660_symlink }, /* symlink */
935: { &vop_readdir_desc, cd9660_readdir }, /* readdir */
936: { &vop_readlink_desc, cd9660_readlink }, /* readlink */
937: { &vop_abortop_desc, cd9660_abortop }, /* abortop */
938: { &vop_inactive_desc, cd9660_inactive }, /* inactive */
939: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */
940: { &vop_lock_desc, genfs_lock }, /* lock */
941: { &vop_unlock_desc, genfs_unlock }, /* unlock */
942: { &vop_bmap_desc, cd9660_bmap }, /* bmap */
943: { &vop_strategy_desc, cd9660_strategy }, /* strategy */
944: { &vop_print_desc, cd9660_print }, /* print */
945: { &vop_islocked_desc, genfs_islocked }, /* islocked */
946: { &vop_pathconf_desc, cd9660_pathconf }, /* pathconf */
947: { &vop_advlock_desc, cd9660_advlock }, /* advlock */
948: { &vop_blkatoff_desc, cd9660_blkatoff }, /* blkatoff */
949: { &vop_valloc_desc, cd9660_valloc }, /* valloc */
950: { &vop_vfree_desc, cd9660_vfree }, /* vfree */
951: { &vop_truncate_desc, cd9660_truncate }, /* truncate */
952: { &vop_update_desc, cd9660_update }, /* update */
953: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
954: { &vop_getpages_desc, genfs_getpages }, /* getpages */
955: { &vop_putpages_desc, genfs_putpages }, /* putpages */
956: { NULL, NULL }
957: };
958: const struct vnodeopv_desc cd9660_vnodeop_opv_desc =
959: { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
960:
961: /*
962: * Special device vnode ops
963: */
964: int (**cd9660_specop_p) __P((void *));
965: const struct vnodeopv_entry_desc cd9660_specop_entries[] = {
966: { &vop_default_desc, vn_default_error },
967: { &vop_lookup_desc, spec_lookup }, /* lookup */
968: { &vop_create_desc, spec_create }, /* create */
969: { &vop_mknod_desc, spec_mknod }, /* mknod */
970: { &vop_open_desc, spec_open }, /* open */
971: { &vop_close_desc, spec_close }, /* close */
972: { &vop_access_desc, cd9660_access }, /* access */
973: { &vop_getattr_desc, cd9660_getattr }, /* getattr */
974: { &vop_setattr_desc, cd9660_setattr }, /* setattr */
975: { &vop_read_desc, spec_read }, /* read */
976: { &vop_write_desc, spec_write }, /* write */
977: { &vop_lease_desc, spec_lease_check }, /* lease */
978: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
979: { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
980: { &vop_poll_desc, spec_poll }, /* poll */
981: { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */
982: { &vop_revoke_desc, spec_revoke }, /* revoke */
983: { &vop_mmap_desc, spec_mmap }, /* mmap */
984: { &vop_fsync_desc, spec_fsync }, /* fsync */
985: { &vop_seek_desc, spec_seek }, /* seek */
986: { &vop_remove_desc, spec_remove }, /* remove */
987: { &vop_link_desc, spec_link }, /* link */
988: { &vop_rename_desc, spec_rename }, /* rename */
989: { &vop_mkdir_desc, spec_mkdir }, /* mkdir */
990: { &vop_rmdir_desc, spec_rmdir }, /* rmdir */
991: { &vop_symlink_desc, spec_symlink }, /* symlink */
992: { &vop_readdir_desc, spec_readdir }, /* readdir */
993: { &vop_readlink_desc, spec_readlink }, /* readlink */
994: { &vop_abortop_desc, spec_abortop }, /* abortop */
995: { &vop_inactive_desc, cd9660_inactive }, /* inactive */
996: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */
997: { &vop_lock_desc, genfs_lock }, /* lock */
998: { &vop_unlock_desc, genfs_unlock }, /* unlock */
999: { &vop_bmap_desc, spec_bmap }, /* bmap */
1000: { &vop_strategy_desc, spec_strategy }, /* strategy */
1001: { &vop_print_desc, cd9660_print }, /* print */
1002: { &vop_islocked_desc, genfs_islocked }, /* islocked */
1003: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
1004: { &vop_advlock_desc, spec_advlock }, /* advlock */
1005: { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */
1006: { &vop_valloc_desc, spec_valloc }, /* valloc */
1007: { &vop_vfree_desc, spec_vfree }, /* vfree */
1008: { &vop_truncate_desc, spec_truncate }, /* truncate */
1009: { &vop_update_desc, cd9660_update }, /* update */
1010: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
1011: { &vop_getpages_desc, spec_getpages }, /* getpages */
1012: { &vop_putpages_desc, spec_putpages }, /* putpages */
1013: { NULL, NULL }
1014: };
1015: const struct vnodeopv_desc cd9660_specop_opv_desc =
1016: { &cd9660_specop_p, cd9660_specop_entries };
1017:
1018: int (**cd9660_fifoop_p) __P((void *));
1019: const struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
1020: { &vop_default_desc, vn_default_error },
1021: { &vop_lookup_desc, fifo_lookup }, /* lookup */
1022: { &vop_create_desc, fifo_create }, /* create */
1023: { &vop_mknod_desc, fifo_mknod }, /* mknod */
1024: { &vop_open_desc, fifo_open }, /* open */
1025: { &vop_close_desc, fifo_close }, /* close */
1026: { &vop_access_desc, cd9660_access }, /* access */
1027: { &vop_getattr_desc, cd9660_getattr }, /* getattr */
1028: { &vop_setattr_desc, cd9660_setattr }, /* setattr */
1029: { &vop_read_desc, fifo_read }, /* read */
1030: { &vop_write_desc, fifo_write }, /* write */
1031: { &vop_lease_desc, fifo_lease_check }, /* lease */
1032: { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */
1033: { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
1034: { &vop_poll_desc, fifo_poll }, /* poll */
1035: { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */
1036: { &vop_revoke_desc, fifo_revoke }, /* revoke */
1037: { &vop_mmap_desc, fifo_mmap }, /* mmap */
1038: { &vop_fsync_desc, fifo_fsync }, /* fsync */
1039: { &vop_seek_desc, fifo_seek }, /* seek */
1040: { &vop_remove_desc, fifo_remove }, /* remove */
1041: { &vop_link_desc, fifo_link } , /* link */
1042: { &vop_rename_desc, fifo_rename }, /* rename */
1043: { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */
1044: { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */
1045: { &vop_symlink_desc, fifo_symlink }, /* symlink */
1046: { &vop_readdir_desc, fifo_readdir }, /* readdir */
1047: { &vop_readlink_desc, fifo_readlink }, /* readlink */
1048: { &vop_abortop_desc, fifo_abortop }, /* abortop */
1049: { &vop_inactive_desc, cd9660_inactive }, /* inactive */
1050: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */
1051: { &vop_lock_desc, genfs_lock }, /* lock */
1052: { &vop_unlock_desc, genfs_unlock }, /* unlock */
1053: { &vop_bmap_desc, fifo_bmap }, /* bmap */
1054: { &vop_strategy_desc, fifo_strategy }, /* strategy */
1055: { &vop_print_desc, cd9660_print }, /* print */
1056: { &vop_islocked_desc, genfs_islocked }, /* islocked */
1057: { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */
1058: { &vop_advlock_desc, fifo_advlock }, /* advlock */
1059: { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */
1060: { &vop_valloc_desc, fifo_valloc }, /* valloc */
1061: { &vop_vfree_desc, fifo_vfree }, /* vfree */
1062: { &vop_truncate_desc, fifo_truncate }, /* truncate */
1063: { &vop_update_desc, cd9660_update }, /* update */
1064: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
1065: { &vop_putpages_desc, fifo_putpages }, /* putpages */
1066: { NULL, NULL }
1067: };
1068: const struct vnodeopv_desc cd9660_fifoop_opv_desc =
1069: { &cd9660_fifoop_p, cd9660_fifoop_entries };
CVSweb <webmaster@jp.NetBSD.org>