Annotation of sys/isofs/cd9660/cd9660_vnops.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cd9660_vnops.c,v 1.43 2007/06/06 17:15:13 deraadt Exp $ */
2: /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */
3:
4: /*-
5: * Copyright (c) 1994
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley
9: * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
10: * Support code is derived from software contributed to Berkeley
11: * by Atsushi Murai (amurai@spec.co.jp).
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: *
37: * @(#)cd9660_vnops.c 8.15 (Berkeley) 12/5/94
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/namei.h>
43: #include <sys/resourcevar.h>
44: #include <sys/kernel.h>
45: #include <sys/file.h>
46: #include <sys/stat.h>
47: #include <sys/buf.h>
48: #include <sys/proc.h>
49: #include <sys/conf.h>
50: #include <sys/mount.h>
51: #include <sys/vnode.h>
52: #include <sys/malloc.h>
53: #include <sys/pool.h>
54: #include <sys/dirent.h>
55: #include <sys/ioctl.h>
56: #include <sys/ioccom.h>
57: #include <sys/cdio.h>
58: #include <sys/poll.h>
59:
60: #include <miscfs/fifofs/fifo.h>
61: #include <miscfs/specfs/specdev.h>
62:
63: #include <isofs/cd9660/iso.h>
64: #include <isofs/cd9660/cd9660_extern.h>
65: #include <isofs/cd9660/cd9660_node.h>
66: #include <isofs/cd9660/iso_rrip.h>
67:
68: /*
69: * Structure for reading directories
70: */
71: struct isoreaddir {
72: struct dirent saveent;
73: struct dirent assocent;
74: struct dirent current;
75: off_t saveoff;
76: off_t assocoff;
77: off_t curroff;
78: struct uio *uio;
79: off_t uio_off;
80: int eofflag;
81: u_long *cookies;
82: int ncookies;
83: };
84:
85: int iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
86: int iso_shipdir(struct isoreaddir *);
87:
88: #if 0
89: /*
90: * Mknod vnode call
91: * Actually remap the device number
92: */
93: int
94: cd9660_mknod(ndp, vap, cred, p)
95: struct nameidata *ndp;
96: struct ucred *cred;
97: struct vattr *vap;
98: struct proc *p;
99: {
100: #ifndef ISODEVMAP
101: pool_put(&namei_pool, ndp->ni_pnbuf);
102: vput(ndp->ni_dvp);
103: vput(ndp->ni_vp);
104: return (EINVAL);
105: #else
106: register struct vnode *vp;
107: struct iso_node *ip;
108: struct iso_dnode *dp;
109: int error;
110:
111: vp = ndp->ni_vp;
112: ip = VTOI(vp);
113:
114: if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
115: || vap->va_type != vp->v_type
116: || (vap->va_type != VCHR && vap->va_type != VBLK)) {
117: pool_put(&namei_pool, ndp->ni_pnbuf);
118: vput(ndp->ni_dvp);
119: vput(ndp->ni_vp);
120: return (EINVAL);
121: }
122:
123: dp = iso_dmap(ip->i_dev,ip->i_number,1);
124: if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
125: /* same as the unmapped one, delete the mapping */
126: remque(dp);
127: FREE(dp, M_CACHE);
128: } else
129: /* enter new mapping */
130: dp->d_dev = vap->va_rdev;
131:
132: /*
133: * Remove inode so that it will be reloaded by iget and
134: * checked to see if it is an alias of an existing entry
135: * in the inode cache.
136: */
137: vput(vp);
138: vp->v_type = VNON;
139: vgone(vp);
140: return (0);
141: #endif
142: }
143: #endif
144:
145: /*
146: * Setattr call. Only allowed for block and character special devices.
147: */
148: int
149: cd9660_setattr(v)
150: void *v;
151: {
152: struct vop_setattr_args *ap = v;
153: struct vnode *vp = ap->a_vp;
154: struct vattr *vap = ap->a_vap;
155:
156: if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
157: vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
158: vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
159: return (EROFS);
160: if (vap->va_size != VNOVAL) {
161: switch (vp->v_type) {
162: case VDIR:
163: return (EISDIR);
164: case VLNK:
165: case VREG:
166: return (EROFS);
167: case VCHR:
168: case VBLK:
169: case VSOCK:
170: case VFIFO:
171: return (0);
172: default:
173: return (EINVAL);
174: }
175: }
176:
177: return (EINVAL);
178: }
179:
180: /*
181: * Open called.
182: *
183: * Nothing to do.
184: */
185: /* ARGSUSED */
186: int
187: cd9660_open(v)
188: void *v;
189: {
190: return (0);
191: }
192:
193: /*
194: * Close called
195: *
196: * Update the times on the inode on writeable file systems.
197: */
198: /* ARGSUSED */
199: int
200: cd9660_close(v)
201: void *v;
202: {
203: return (0);
204: }
205:
206: /*
207: * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
208: * The mode is shifted to select the owner/group/other fields. The
209: * super user is granted all permissions.
210: */
211: int
212: cd9660_access(v)
213: void *v;
214: {
215: struct vop_access_args *ap = v;
216: struct iso_node *ip = VTOI(ap->a_vp);
217:
218: return (vaccess(ip->inode.iso_mode & ALLPERMS, ip->inode.iso_uid,
219: ip->inode.iso_gid, ap->a_mode, ap->a_cred));
220: }
221:
222: int
223: cd9660_getattr(v)
224: void *v;
225: {
226: struct vop_getattr_args *ap = v;
227: struct vnode *vp = ap->a_vp;
228: register struct vattr *vap = ap->a_vap;
229: register struct iso_node *ip = VTOI(vp);
230:
231: vap->va_fsid = ip->i_dev;
232: vap->va_fileid = ip->i_number;
233:
234: vap->va_mode = ip->inode.iso_mode & ALLPERMS;
235: vap->va_nlink = ip->inode.iso_links;
236: vap->va_uid = ip->inode.iso_uid;
237: vap->va_gid = ip->inode.iso_gid;
238: vap->va_atime = ip->inode.iso_atime;
239: vap->va_mtime = ip->inode.iso_mtime;
240: vap->va_ctime = ip->inode.iso_ctime;
241: vap->va_rdev = ip->inode.iso_rdev;
242:
243: vap->va_size = (u_quad_t) ip->i_size;
244: if (ip->i_size == 0 && vp->v_type == VLNK) {
245: struct vop_readlink_args rdlnk;
246: struct iovec aiov;
247: struct uio auio;
248: char *cp;
249:
250: MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
251: aiov.iov_base = cp;
252: aiov.iov_len = MAXPATHLEN;
253: auio.uio_iov = &aiov;
254: auio.uio_iovcnt = 1;
255: auio.uio_offset = 0;
256: auio.uio_rw = UIO_READ;
257: auio.uio_segflg = UIO_SYSSPACE;
258: auio.uio_procp = ap->a_p;
259: auio.uio_resid = MAXPATHLEN;
260: rdlnk.a_uio = &auio;
261: rdlnk.a_vp = ap->a_vp;
262: rdlnk.a_cred = ap->a_cred;
263: if (cd9660_readlink(&rdlnk) == 0)
264: vap->va_size = MAXPATHLEN - auio.uio_resid;
265: FREE(cp, M_TEMP);
266: }
267: vap->va_flags = 0;
268: vap->va_gen = 1;
269: vap->va_blocksize = ip->i_mnt->logical_block_size;
270: vap->va_bytes = (u_quad_t) ip->i_size;
271: vap->va_type = vp->v_type;
272: return (0);
273: }
274:
275: /*
276: * Vnode op for reading.
277: */
278: int
279: cd9660_read(v)
280: void *v;
281: {
282: struct vop_read_args *ap = v;
283: struct vnode *vp = ap->a_vp;
284: register struct uio *uio = ap->a_uio;
285: register struct iso_node *ip = VTOI(vp);
286: register struct iso_mnt *imp;
287: struct buf *bp;
288: daddr64_t lbn, rablock;
289: off_t diff;
290: int error = 0;
291: long size, n, on;
292:
293: if (uio->uio_resid == 0)
294: return (0);
295: if (uio->uio_offset < 0)
296: return (EINVAL);
297: ip->i_flag |= IN_ACCESS;
298: imp = ip->i_mnt;
299: do {
300: struct cluster_info *ci = &ip->i_ci;
301:
302: lbn = lblkno(imp, uio->uio_offset);
303: on = blkoff(imp, uio->uio_offset);
304: n = min((u_int)(imp->logical_block_size - on),
305: uio->uio_resid);
306: diff = (off_t)ip->i_size - uio->uio_offset;
307: if (diff <= 0)
308: return (0);
309: if (diff < n)
310: n = diff;
311: size = blksize(imp, ip, lbn);
312: rablock = lbn + 1;
313: #define MAX_RA 32
314: if (ci->ci_lastr + 1 == lbn) {
315: struct ra {
316: daddr64_t blks[MAX_RA];
317: int sizes[MAX_RA];
318: } *ra;
319: int i;
320:
321: MALLOC(ra, struct ra *, sizeof *ra,
322: M_TEMP, M_WAITOK);
323: for (i = 0; i < MAX_RA &&
324: lblktosize(imp, (rablock + i)) < ip->i_size;
325: i++) {
326: ra->blks[i] = rablock + i;
327: ra->sizes[i] = blksize(imp, ip, rablock + i);
328: }
329: error = breadn(vp, lbn, size, ra->blks,
330: ra->sizes, i, NOCRED, &bp);
331: FREE(ra, M_TEMP);
332: } else
333: error = bread(vp, lbn, size, NOCRED, &bp);
334: ci->ci_lastr = lbn;
335: n = min(n, size - bp->b_resid);
336: if (error) {
337: brelse(bp);
338: return (error);
339: }
340:
341: error = uiomove(bp->b_data + on, (int)n, uio);
342:
343: if (n + on == imp->logical_block_size ||
344: uio->uio_offset == (off_t)ip->i_size)
345: bp->b_flags |= B_AGE;
346: brelse(bp);
347: } while (error == 0 && uio->uio_resid > 0 && n != 0);
348: return (error);
349: }
350:
351: /* ARGSUSED */
352: int
353: cd9660_ioctl(v)
354: void *v;
355: {
356: return (ENOTTY);
357: }
358:
359: /* ARGSUSED */
360: int
361: cd9660_poll(v)
362: void *v;
363: {
364: struct vop_poll_args *ap = v;
365:
366: /*
367: * We should really check to see if I/O is possible.
368: */
369: return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
370: }
371:
372: /*
373: * Mmap a file
374: *
375: * NB Currently unsupported.
376: */
377: /* ARGSUSED */
378: int
379: cd9660_mmap(v)
380: void *v;
381: {
382:
383: return (EINVAL);
384: }
385:
386: /*
387: * Seek on a file
388: *
389: * Nothing to do, so just return.
390: */
391: /* ARGSUSED */
392: int
393: cd9660_seek(v)
394: void *v;
395: {
396: return (0);
397: }
398:
399: int
400: iso_uiodir(idp,dp,off)
401: struct isoreaddir *idp;
402: struct dirent *dp;
403: off_t off;
404: {
405: int error;
406:
407: dp->d_name[dp->d_namlen] = 0;
408: dp->d_reclen = DIRENT_SIZE(dp);
409:
410: if (idp->uio->uio_resid < dp->d_reclen) {
411: idp->eofflag = 0;
412: return (-1);
413: }
414:
415: if (idp->cookies) {
416: if (idp->ncookies <= 0) {
417: idp->eofflag = 0;
418: return (-1);
419: }
420:
421: *idp->cookies++ = off;
422: --idp->ncookies;
423: }
424:
425: if ((error = uiomove((caddr_t)dp, dp->d_reclen, idp->uio)) != 0)
426: return (error);
427: idp->uio_off = off;
428: return (0);
429: }
430:
431: int
432: iso_shipdir(idp)
433: struct isoreaddir *idp;
434: {
435: struct dirent *dp;
436: int cl, sl, assoc;
437: int error;
438: char *cname, *sname;
439:
440: cl = idp->current.d_namlen;
441: cname = idp->current.d_name;
442:
443: if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
444: cl--;
445: cname++;
446: }
447:
448: dp = &idp->saveent;
449: sname = dp->d_name;
450: if (!(sl = dp->d_namlen)) {
451: dp = &idp->assocent;
452: sname = dp->d_name + 1;
453: sl = dp->d_namlen - 1;
454: }
455: if (sl > 0) {
456: if (sl != cl
457: || bcmp(sname,cname,sl)) {
458: if (idp->assocent.d_namlen) {
459: error = iso_uiodir(idp, &idp->assocent,
460: idp->assocoff);
461: if (error)
462: return (error);
463: idp->assocent.d_namlen = 0;
464: }
465: if (idp->saveent.d_namlen) {
466: error = iso_uiodir(idp, &idp->saveent,
467: idp->saveoff);
468: if (error)
469: return (error);
470: idp->saveent.d_namlen = 0;
471: }
472: }
473: }
474: idp->current.d_reclen = DIRENT_SIZE(&idp->current);
475: if (assoc) {
476: idp->assocoff = idp->curroff;
477: bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
478: } else {
479: idp->saveoff = idp->curroff;
480: bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
481: }
482: return (0);
483: }
484:
485: /*
486: * Vnode op for readdir
487: */
488: int
489: cd9660_readdir(v)
490: void *v;
491: {
492: struct vop_readdir_args *ap = v;
493: register struct uio *uio = ap->a_uio;
494: struct isoreaddir *idp;
495: struct vnode *vdp = ap->a_vp;
496: struct iso_node *dp;
497: struct iso_mnt *imp;
498: struct buf *bp = NULL;
499: struct iso_directory_record *ep;
500: int entryoffsetinblock;
501: doff_t endsearch;
502: u_long bmask;
503: int error = 0;
504: int reclen;
505: u_short namelen;
506: int ncookies = 0;
507: u_long *cookies = NULL;
508:
509: dp = VTOI(vdp);
510: imp = dp->i_mnt;
511: bmask = imp->im_bmask;
512:
513: MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
514: idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
515: /*
516: * XXX
517: * Is it worth trying to figure out the type?
518: */
519: idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
520: DT_UNKNOWN;
521: idp->uio = uio;
522: if (ap->a_ncookies == NULL) {
523: idp->cookies = NULL;
524: } else {
525: /*
526: * Guess the number of cookies needed.
527: */
528: ncookies = uio->uio_resid / 16;
529: MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
530: M_WAITOK);
531: idp->cookies = cookies;
532: idp->ncookies = ncookies;
533: }
534: idp->eofflag = 1;
535: idp->curroff = uio->uio_offset;
536:
537: if ((entryoffsetinblock = idp->curroff & bmask) &&
538: (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) {
539: FREE(idp, M_TEMP);
540: return (error);
541: }
542: endsearch = dp->i_size;
543:
544: while (idp->curroff < endsearch) {
545: /*
546: * If offset is on a block boundary,
547: * read the next directory block.
548: * Release previous if it exists.
549: */
550: if ((idp->curroff & bmask) == 0) {
551: if (bp != NULL)
552: brelse(bp);
553: error = cd9660_bufatoff(dp, (off_t)idp->curroff,
554: NULL, &bp);
555: if (error)
556: break;
557: entryoffsetinblock = 0;
558: }
559: /*
560: * Get pointer to next entry.
561: */
562: ep = (struct iso_directory_record *)
563: ((char *)bp->b_data + entryoffsetinblock);
564:
565: reclen = isonum_711(ep->length);
566: if (reclen == 0) {
567: /* skip to next block, if any */
568: idp->curroff =
569: (idp->curroff & ~bmask) + imp->logical_block_size;
570: continue;
571: }
572:
573: if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
574: error = EINVAL;
575: /* illegal entry, stop */
576: break;
577: }
578:
579: if (entryoffsetinblock + reclen > imp->logical_block_size) {
580: error = EINVAL;
581: /* illegal directory, so stop looking */
582: break;
583: }
584:
585: idp->current.d_namlen = isonum_711(ep->name_len);
586:
587: if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
588: error = EINVAL;
589: /* illegal entry, stop */
590: break;
591: }
592:
593: if (isonum_711(ep->flags)&2)
594: idp->current.d_fileno = isodirino(ep, imp);
595: else
596: idp->current.d_fileno = dbtob(bp->b_blkno) +
597: entryoffsetinblock;
598:
599: idp->curroff += reclen;
600:
601: switch (imp->iso_ftype) {
602: case ISO_FTYPE_RRIP:
603: cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
604: &idp->current.d_fileno,imp);
605: idp->current.d_namlen = (u_char)namelen;
606: if (idp->current.d_namlen)
607: error = iso_uiodir(idp,&idp->current,idp->curroff);
608: break;
609: default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
610: strlcpy(idp->current.d_name,"..",
611: sizeof idp->current.d_name);
612: if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
613: idp->current.d_namlen = 1;
614: error = iso_uiodir(idp,&idp->current,idp->curroff);
615: } else if (idp->current.d_namlen == 1 &&
616: ep->name[0] == 1) {
617: idp->current.d_namlen = 2;
618: error = iso_uiodir(idp,&idp->current,idp->curroff);
619: } else {
620: isofntrans(ep->name,idp->current.d_namlen,
621: idp->current.d_name, &namelen,
622: imp->iso_ftype == ISO_FTYPE_9660,
623: isonum_711(ep->flags) & 4,
624: imp->joliet_level);
625: idp->current.d_namlen = (u_char)namelen;
626: if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
627: error = iso_shipdir(idp);
628: else
629: error = iso_uiodir(idp,&idp->current,idp->curroff);
630: }
631: }
632: if (error)
633: break;
634:
635: entryoffsetinblock += reclen;
636: }
637:
638: if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
639: idp->current.d_namlen = 0;
640: error = iso_shipdir(idp);
641: }
642: if (error < 0)
643: error = 0;
644:
645: if (ap->a_ncookies != NULL) {
646: if (error)
647: free(cookies, M_TEMP);
648: else {
649: /*
650: * Work out the number of cookies actually used.
651: */
652: *ap->a_ncookies = ncookies - idp->ncookies;
653: *ap->a_cookies = cookies;
654: }
655: }
656:
657: if (bp)
658: brelse (bp);
659:
660: uio->uio_offset = idp->uio_off;
661: *ap->a_eofflag = idp->eofflag;
662:
663: FREE(idp, M_TEMP);
664:
665: return (error);
666: }
667:
668: /*
669: * Return target name of a symbolic link
670: * Shouldn't we get the parent vnode and read the data from there?
671: * This could eventually result in deadlocks in cd9660_lookup.
672: * But otherwise the block read here is in the block buffer two times.
673: */
674: typedef struct iso_directory_record ISODIR;
675: typedef struct iso_node ISONODE;
676: typedef struct iso_mnt ISOMNT;
677: int
678: cd9660_readlink(v)
679: void *v;
680: {
681: struct vop_readlink_args *ap = v;
682: ISONODE *ip;
683: ISODIR *dirp;
684: ISOMNT *imp;
685: struct buf *bp;
686: struct uio *uio;
687: u_short symlen;
688: int error;
689: char *symname;
690:
691: ip = VTOI(ap->a_vp);
692: imp = ip->i_mnt;
693: uio = ap->a_uio;
694:
695: if (imp->iso_ftype != ISO_FTYPE_RRIP)
696: return (EINVAL);
697:
698: /*
699: * Get parents directory record block that this inode included.
700: */
701: error = bread(imp->im_devvp,
702: (ip->i_number >> imp->im_bshift) <<
703: (imp->im_bshift - DEV_BSHIFT),
704: imp->logical_block_size, NOCRED, &bp);
705: if (error) {
706: brelse(bp);
707: return (EINVAL);
708: }
709:
710: /*
711: * Setup the directory pointer for this inode
712: */
713: dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
714:
715: /*
716: * Just make sure, we have a right one....
717: * 1: Check not cross boundary on block
718: */
719: if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
720: > imp->logical_block_size) {
721: brelse(bp);
722: return (EINVAL);
723: }
724:
725: /*
726: * Now get a buffer
727: * Abuse a namei buffer for now.
728: */
729: if (uio->uio_segflg == UIO_SYSSPACE &&
730: uio->uio_iov->iov_len >= MAXPATHLEN)
731: symname = uio->uio_iov->iov_base;
732: else
733: symname = pool_get(&namei_pool, PR_WAITOK);
734:
735: /*
736: * Ok, we just gathering a symbolic name in SL record.
737: */
738: if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
739: if (uio->uio_segflg != UIO_SYSSPACE ||
740: uio->uio_iov->iov_len < MAXPATHLEN)
741: pool_put(&namei_pool, symname);
742: brelse(bp);
743: return (EINVAL);
744: }
745: /*
746: * Don't forget before you leave from home ;-)
747: */
748: brelse(bp);
749:
750: /*
751: * return with the symbolic name to caller's.
752: */
753: if (uio->uio_segflg != UIO_SYSSPACE ||
754: uio->uio_iov->iov_len < MAXPATHLEN) {
755: error = uiomove(symname, symlen, uio);
756: pool_put(&namei_pool, symname);
757: return (error);
758: }
759: uio->uio_resid -= symlen;
760: (char *)uio->uio_iov->iov_base += symlen;
761: uio->uio_iov->iov_len -= symlen;
762: return (0);
763: }
764:
765: int
766: cd9660_link(v)
767: void *v;
768: {
769: struct vop_link_args *ap = v;
770:
771: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
772: vput(ap->a_dvp);
773: return (EROFS);
774: }
775:
776: int
777: cd9660_symlink(v)
778: void *v;
779: {
780: struct vop_symlink_args *ap = v;
781:
782: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
783: vput(ap->a_dvp);
784: return (EROFS);
785: }
786:
787: /*
788: * Lock an inode.
789: */
790: int
791: cd9660_lock(v)
792: void *v;
793: {
794: struct vop_lock_args *ap = v;
795: struct vnode *vp = ap->a_vp;
796:
797: return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
798: }
799:
800: /*
801: * Unlock an inode.
802: */
803: int
804: cd9660_unlock(v)
805: void *v;
806: {
807: struct vop_unlock_args *ap = v;
808: struct vnode *vp = ap->a_vp;
809:
810: return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
811: }
812:
813: /*
814: * Calculate the logical to physical mapping if not done already,
815: * then call the device strategy routine.
816: */
817: int
818: cd9660_strategy(v)
819: void *v;
820: {
821: struct vop_strategy_args *ap = v;
822: struct buf *bp = ap->a_bp;
823: struct vnode *vp = bp->b_vp;
824: struct iso_node *ip;
825: int error;
826: int s;
827:
828: ip = VTOI(vp);
829: if (vp->v_type == VBLK || vp->v_type == VCHR)
830: panic("cd9660_strategy: spec");
831: if (bp->b_blkno == bp->b_lblkno) {
832: error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
833: if (error) {
834: bp->b_error = error;
835: bp->b_flags |= B_ERROR;
836: s = splbio();
837: biodone(bp);
838: splx(s);
839: return (error);
840: }
841: if ((long)bp->b_blkno == -1)
842: clrbuf(bp);
843: }
844: if ((long)bp->b_blkno == -1) {
845: s = splbio();
846: biodone(bp);
847: splx(s);
848: return (0);
849: }
850: vp = ip->i_devvp;
851: bp->b_dev = vp->v_rdev;
852: VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
853: return (0);
854: }
855:
856: /*
857: * Print out the contents of an inode.
858: */
859: /*ARGSUSED*/
860: int
861: cd9660_print(v)
862: void *v;
863: {
864: printf("tag VT_ISOFS, isofs vnode\n");
865: return (0);
866: }
867:
868: /*
869: * Check for a locked inode.
870: */
871: int
872: cd9660_islocked(v)
873: void *v;
874: {
875: struct vop_islocked_args *ap = v;
876:
877: return (lockstatus(&VTOI(ap->a_vp)->i_lock));
878: }
879:
880: /*
881: * Return POSIX pathconf information applicable to cd9660 filesystems.
882: */
883: int
884: cd9660_pathconf(v)
885: void *v;
886: {
887: struct vop_pathconf_args *ap = v;
888: switch (ap->a_name) {
889: case _PC_LINK_MAX:
890: *ap->a_retval = 1;
891: return (0);
892: case _PC_NAME_MAX:
893: if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
894: *ap->a_retval = NAME_MAX;
895: else
896: *ap->a_retval = 37;
897: return (0);
898: case _PC_PATH_MAX:
899: *ap->a_retval = PATH_MAX;
900: return (0);
901: case _PC_PIPE_BUF:
902: *ap->a_retval = PIPE_BUF;
903: return (0);
904: case _PC_CHOWN_RESTRICTED:
905: *ap->a_retval = 1;
906: return (0);
907: case _PC_NO_TRUNC:
908: *ap->a_retval = 1;
909: return (0);
910: default:
911: return (EINVAL);
912: }
913: /* NOTREACHED */
914: }
915:
916: /*
917: * Global vfs data structures for isofs
918: */
919: #define cd9660_create eopnotsupp
920: #define cd9660_mknod eopnotsupp
921: #define cd9660_write eopnotsupp
922: #define cd9660_fsync nullop
923: #define cd9660_remove eopnotsupp
924: #define cd9660_rename eopnotsupp
925: #define cd9660_mkdir eopnotsupp
926: #define cd9660_rmdir eopnotsupp
927: #define cd9660_advlock eopnotsupp
928: #define cd9660_valloc eopnotsupp
929: #define cd9660_vfree eopnotsupp
930: #define cd9660_truncate eopnotsupp
931: #define cd9660_update eopnotsupp
932: #define cd9660_bwrite eopnotsupp
933: #define cd9660_revoke vop_generic_revoke
934:
935: /*
936: * Global vfs data structures for cd9660
937: */
938: int (**cd9660_vnodeop_p)(void *);
939: struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
940: { &vop_default_desc, vn_default_error },
941: { &vop_lookup_desc, cd9660_lookup }, /* lookup */
942: { &vop_create_desc, cd9660_create }, /* create */
943: { &vop_mknod_desc, cd9660_mknod }, /* mknod */
944: { &vop_open_desc, cd9660_open }, /* open */
945: { &vop_close_desc, cd9660_close }, /* close */
946: { &vop_access_desc, cd9660_access }, /* access */
947: { &vop_getattr_desc, cd9660_getattr }, /* getattr */
948: { &vop_setattr_desc, cd9660_setattr }, /* setattr */
949: { &vop_read_desc, cd9660_read }, /* read */
950: { &vop_write_desc, cd9660_write }, /* write */
951: { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */
952: { &vop_poll_desc, cd9660_poll }, /* poll */
953: { &vop_revoke_desc, cd9660_revoke }, /* revoke */
954: { &vop_fsync_desc, cd9660_fsync }, /* fsync */
955: { &vop_remove_desc, cd9660_remove }, /* remove */
956: { &vop_link_desc, cd9660_link }, /* link */
957: { &vop_rename_desc, cd9660_rename }, /* rename */
958: { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */
959: { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */
960: { &vop_symlink_desc, cd9660_symlink }, /* symlink */
961: { &vop_readdir_desc, cd9660_readdir }, /* readdir */
962: { &vop_readlink_desc, cd9660_readlink },/* readlink */
963: { &vop_abortop_desc, vop_generic_abortop }, /* abortop */
964: { &vop_inactive_desc, cd9660_inactive },/* inactive */
965: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */
966: { &vop_lock_desc, cd9660_lock }, /* lock */
967: { &vop_unlock_desc, cd9660_unlock }, /* unlock */
968: { &vop_bmap_desc, cd9660_bmap }, /* bmap */
969: { &vop_strategy_desc, cd9660_strategy },/* strategy */
970: { &vop_print_desc, cd9660_print }, /* print */
971: { &vop_islocked_desc, cd9660_islocked },/* islocked */
972: { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
973: { &vop_advlock_desc, cd9660_advlock }, /* advlock */
974: { &vop_bwrite_desc, vop_generic_bwrite },
975: { NULL, NULL }
976: };
977: struct vnodeopv_desc cd9660_vnodeop_opv_desc =
978: { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
979:
980: /*
981: * Special device vnode ops
982: */
983: int (**cd9660_specop_p)(void *);
984: struct vnodeopv_entry_desc cd9660_specop_entries[] = {
985: { &vop_default_desc, spec_vnoperate },
986: { &vop_access_desc, cd9660_access }, /* access */
987: { &vop_getattr_desc, cd9660_getattr }, /* getattr */
988: { &vop_setattr_desc, cd9660_setattr }, /* setattr */
989: { &vop_inactive_desc, cd9660_inactive },/* inactive */
990: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */
991: { &vop_lock_desc, cd9660_lock }, /* lock */
992: { &vop_unlock_desc, cd9660_unlock }, /* unlock */
993: { &vop_print_desc, cd9660_print }, /* print */
994: { &vop_islocked_desc, cd9660_islocked },/* islocked */
995: { NULL, NULL }
996: };
997: struct vnodeopv_desc cd9660_specop_opv_desc =
998: { &cd9660_specop_p, cd9660_specop_entries };
999:
1000: #ifdef FIFO
1001: int (**cd9660_fifoop_p)(void *);
1002: struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
1003: { &vop_default_desc, fifo_vnoperate },
1004: { &vop_access_desc, cd9660_access }, /* access */
1005: { &vop_getattr_desc, cd9660_getattr }, /* getattr */
1006: { &vop_setattr_desc, cd9660_setattr }, /* setattr */
1007: { &vop_inactive_desc, cd9660_inactive },/* inactive */
1008: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */
1009: { &vop_lock_desc, cd9660_lock }, /* lock */
1010: { &vop_unlock_desc, cd9660_unlock }, /* unlock */
1011: { &vop_print_desc, cd9660_print }, /* print */
1012: { &vop_islocked_desc, cd9660_islocked },/* islocked */
1013: { &vop_bwrite_desc, vop_generic_bwrite },
1014: { NULL, NULL }
1015: };
1016: struct vnodeopv_desc cd9660_fifoop_opv_desc =
1017: { &cd9660_fifoop_p, cd9660_fifoop_entries };
1018: #endif /* FIFO */
CVSweb