]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
8ad349bb | 2 | * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 3 | * |
8ad349bb | 4 | * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ |
1c79356b | 5 | * |
8ad349bb A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the | |
10 | * License may not be used to create, or enable the creation or | |
11 | * redistribution of, unlawful or unlicensed copies of an Apple operating | |
12 | * system, or to circumvent, violate, or enable the circumvention or | |
13 | * violation of, any terms of an Apple operating system software license | |
14 | * agreement. | |
15 | * | |
16 | * Please obtain a copy of the License at | |
17 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
18 | * file. | |
19 | * | |
20 | * The Original Code and all software distributed under the License are | |
21 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
22 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
23 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
24 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
25 | * Please see the License for the specific language governing rights and | |
26 | * limitations under the License. | |
27 | * | |
28 | * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ | |
1c79356b A |
29 | */ |
30 | /* $NetBSD: cd9660_vnops.c,v 1.22 1994/12/27 19:05:12 mycroft Exp $ */ | |
31 | ||
32 | /*- | |
33 | * Copyright (c) 1994 | |
34 | * The Regents of the University of California. All rights reserved. | |
35 | * | |
36 | * This code is derived from software contributed to Berkeley | |
37 | * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension | |
38 | * Support code is derived from software contributed to Berkeley | |
39 | * by Atsushi Murai (amurai@spec.co.jp). | |
40 | * | |
41 | * Redistribution and use in source and binary forms, with or without | |
42 | * modification, are permitted provided that the following conditions | |
43 | * are met: | |
44 | * 1. Redistributions of source code must retain the above copyright | |
45 | * notice, this list of conditions and the following disclaimer. | |
46 | * 2. Redistributions in binary form must reproduce the above copyright | |
47 | * notice, this list of conditions and the following disclaimer in the | |
48 | * documentation and/or other materials provided with the distribution. | |
49 | * 3. All advertising materials mentioning features or use of this software | |
50 | * must display the following acknowledgement: | |
51 | * This product includes software developed by the University of | |
52 | * California, Berkeley and its contributors. | |
53 | * 4. Neither the name of the University nor the names of its contributors | |
54 | * may be used to endorse or promote products derived from this software | |
55 | * without specific prior written permission. | |
56 | * | |
57 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
58 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
59 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
60 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
61 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
62 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
63 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
64 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
65 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
66 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
67 | * SUCH DAMAGE. | |
68 | * | |
69 | * @(#)cd9660_vnops.c 8.15 (Berkeley) 12/5/94 | |
70 | * | |
71 | * HISTORY | |
72 | * 02-Feb-00 chw Add cd9660_copyfile to return error | |
73 | * 29-Sep-98 djb Add cd9660_getattrlist VOP for VDI support. | |
74 | * 15-sep-98 added cd9660_rmdir to do proper unlocking - chw | |
75 | * 12-aug-98 added cd9660_remove which will do proper unlocking - chw | |
76 | * 17-Feb-98 radar 1669467 - changed lock protocols to use the lock manager - chw | |
77 | * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc | |
78 | */ | |
79 | ||
80 | #include <sys/param.h> | |
81 | #include <sys/systm.h> | |
82 | #include <sys/vnode.h> | |
83 | #include <sys/mount.h> | |
84 | #include <sys/namei.h> | |
85 | #include <sys/resourcevar.h> | |
86 | #include <sys/kernel.h> | |
87 | #include <sys/file.h> | |
88 | #include <sys/stat.h> | |
89 | #include <sys/buf.h> | |
90 | #include <sys/proc.h> | |
91447636 | 91 | #include <sys/kauth.h> |
1c79356b A |
92 | #include <sys/conf.h> |
93 | #include <miscfs/specfs/specdev.h> | |
94 | #include <miscfs/fifofs/fifo.h> | |
95 | #include <sys/malloc.h> | |
96 | #include <sys/dir.h> | |
97 | #include <sys/attr.h> | |
98 | #include <vfs/vfs_support.h> | |
91447636 | 99 | #include <vm/vm_kern.h> |
1c79356b | 100 | #include <sys/ubc.h> |
1c79356b | 101 | #include <sys/lock.h> |
91447636 A |
102 | #include <sys/ubc_internal.h> |
103 | #include <sys/uio_internal.h> | |
8ad349bb | 104 | #include <architecture/byte_order.h> |
1c79356b | 105 | |
91447636 A |
106 | #include <vm/vm_map.h> |
107 | #include <vm/vm_kern.h> /* kmem_alloc, kmem_free */ | |
108 | ||
1c79356b A |
109 | #include <isofs/cd9660/iso.h> |
110 | #include <isofs/cd9660/cd9660_node.h> | |
111 | #include <isofs/cd9660/iso_rrip.h> | |
112 | ||
113 | /* | |
114 | * Open called. | |
115 | * | |
116 | * Nothing to do. | |
117 | */ | |
1c79356b | 118 | int |
91447636 | 119 | cd9660_open(__unused struct vnop_open_args *ap) |
1c79356b A |
120 | { |
121 | return (0); | |
122 | } | |
123 | ||
124 | /* | |
125 | * Close called | |
126 | * | |
127 | * Update the times on the inode on writeable file systems. | |
128 | */ | |
1c79356b | 129 | int |
91447636 | 130 | cd9660_close(__unused struct vnop_close_args *ap) |
1c79356b A |
131 | { |
132 | return (0); | |
133 | } | |
134 | ||
1c79356b | 135 | int |
91447636 | 136 | cd9660_getattr(struct vnop_getattr_args *ap) |
1c79356b A |
137 | { |
138 | struct vnode *vp = ap->a_vp; | |
91447636 | 139 | register struct vnode_attr *vap = ap->a_vap; |
1c79356b A |
140 | register struct iso_node *ip = VTOI(vp); |
141 | ||
91447636 A |
142 | VATTR_RETURN(vap, va_fsid, ip->i_dev); |
143 | VATTR_RETURN(vap, va_fileid, ip->i_number); | |
1c79356b | 144 | |
91447636 A |
145 | VATTR_RETURN(vap, va_mode, ip->inode.iso_mode); |
146 | VATTR_RETURN(vap, va_nlink, ip->inode.iso_links); | |
147 | VATTR_RETURN(vap, va_uid, ip->inode.iso_uid); | |
148 | VATTR_RETURN(vap, va_gid, ip->inode.iso_gid); | |
149 | VATTR_RETURN(vap, va_access_time, ip->inode.iso_atime); | |
150 | VATTR_RETURN(vap, va_modify_time, ip->inode.iso_mtime); | |
151 | VATTR_RETURN(vap, va_change_time, ip->inode.iso_ctime); | |
152 | VATTR_RETURN(vap, va_rdev, ip->inode.iso_rdev); | |
1c79356b | 153 | |
91447636 | 154 | VATTR_RETURN(vap, va_data_size, (off_t)ip->i_size); |
1c79356b | 155 | if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { |
91447636 A |
156 | struct vnop_readlink_args rdlnk; |
157 | uio_t auio; | |
158 | char uio_buf[ UIO_SIZEOF(1) ]; | |
1c79356b A |
159 | char *cp; |
160 | ||
161 | MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); | |
91447636 A |
162 | auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ, |
163 | &uio_buf[0], sizeof(uio_buf)); | |
164 | uio_addiov(auio, CAST_USER_ADDR_T(cp), MAXPATHLEN); | |
165 | ||
166 | rdlnk.a_uio = auio; | |
1c79356b | 167 | rdlnk.a_vp = ap->a_vp; |
91447636 | 168 | rdlnk.a_context = ap->a_context; |
1c79356b | 169 | if (cd9660_readlink(&rdlnk) == 0) |
91447636 A |
170 | // LP64todo - fix this! |
171 | VATTR_RETURN(vap, va_data_size, MAXPATHLEN - uio_resid(auio)); | |
1c79356b A |
172 | FREE(cp, M_TEMP); |
173 | } | |
91447636 A |
174 | VATTR_RETURN(vap, va_flags, 0); |
175 | VATTR_RETURN(vap, va_gen, 1); | |
176 | VATTR_RETURN(vap, va_iosize, ip->i_mnt->logical_block_size); | |
177 | VATTR_RETURN(vap, va_total_size, ip->i_size + ip->i_rsrcsize); | |
1c79356b A |
178 | |
179 | return (0); | |
180 | } | |
181 | ||
182 | ||
183 | /* | |
184 | * Vnode op for reading. | |
185 | */ | |
186 | int | |
91447636 | 187 | cd9660_read(struct vnop_read_args *ap) |
1c79356b A |
188 | { |
189 | struct vnode *vp = ap->a_vp; | |
190 | register struct uio *uio = ap->a_uio; | |
191 | register struct iso_node *ip = VTOI(vp); | |
192 | register struct iso_mnt *imp; | |
193 | struct buf *bp; | |
91447636 A |
194 | daddr_t lbn; |
195 | daddr64_t rablock; | |
1c79356b A |
196 | off_t diff; |
197 | int rasize, error = 0; | |
91447636 | 198 | int32_t size, n, on; |
1c79356b | 199 | |
91447636 | 200 | if (uio_resid(uio) == 0) |
1c79356b A |
201 | return (0); |
202 | if (uio->uio_offset < 0) | |
203 | return (EINVAL); | |
204 | ||
205 | imp = ip->i_mnt; | |
1c79356b | 206 | |
91447636 | 207 | if (UBCINFOEXISTS(vp)) { |
55e303ae A |
208 | /* |
209 | * Copy any part of the Apple Double header. | |
210 | */ | |
211 | if ((ip->i_flag & ISO_ASSOCIATED) && (uio->uio_offset < ADH_SIZE)) { | |
212 | apple_double_header_t header; | |
213 | int bytes; | |
214 | ||
215 | if (uio->uio_offset < sizeof(apple_double_header_t)) { | |
216 | header.magic = APPLEDOUBLE_MAGIC; | |
217 | header.version = APPLEDOUBLE_VERSION; | |
218 | header.count = 2; | |
219 | header.entries[0].entryID = APPLEDOUBLE_FINDERINFO; | |
220 | header.entries[0].offset = offsetof(apple_double_header_t, finfo); | |
221 | header.entries[0].length = 32; | |
222 | header.entries[1].entryID = APPLEDOUBLE_RESFORK; | |
223 | header.entries[1].offset = ADH_SIZE; | |
224 | header.entries[1].length = ip->i_size - ADH_SIZE; | |
225 | header.finfo.fdType = ip->i_FileType; | |
226 | header.finfo.fdCreator = ip->i_Creator; | |
227 | header.finfo.fdFlags = ip->i_FinderFlags; | |
228 | header.finfo.fdLocation.v = -1; | |
229 | header.finfo.fdLocation.h = -1; | |
230 | header.finfo.fdReserved = 0; | |
231 | ||
91447636 | 232 | bytes = min(uio_resid(uio), sizeof(apple_double_header_t) - uio->uio_offset); |
55e303ae A |
233 | error = uiomove(((char *) &header) + uio->uio_offset, bytes, uio); |
234 | if (error) | |
235 | return error; | |
236 | } | |
91447636 | 237 | if (uio_resid(uio) && uio->uio_offset < ADH_SIZE) { |
55e303ae A |
238 | caddr_t buffer; |
239 | ||
240 | if (kmem_alloc(kernel_map, (vm_offset_t *)&buffer, ADH_SIZE)) { | |
241 | return (ENOMEM); | |
242 | } | |
91447636 | 243 | bytes = min(uio_resid(uio), ADH_SIZE - uio->uio_offset); |
55e303ae A |
244 | error = uiomove(((char *) buffer) + uio->uio_offset, bytes, uio); |
245 | kmem_free(kernel_map, (vm_offset_t)buffer, ADH_SIZE); | |
246 | if (error) | |
247 | return error; | |
248 | } | |
249 | } | |
91447636 A |
250 | if (uio_resid(uio) > 0) |
251 | error = cluster_read(vp, uio, (off_t)ip->i_size, 0); | |
55e303ae | 252 | } else { |
1c79356b A |
253 | |
254 | do { | |
255 | lbn = lblkno(imp, uio->uio_offset); | |
256 | on = blkoff(imp, uio->uio_offset); | |
257 | n = min((u_int)(imp->logical_block_size - on), | |
91447636 | 258 | uio_resid(uio)); |
1c79356b A |
259 | diff = (off_t)ip->i_size - uio->uio_offset; |
260 | if (diff <= 0) | |
261 | return (0); | |
262 | if (diff < n) | |
263 | n = diff; | |
264 | size = blksize(imp, ip, lbn); | |
91447636 | 265 | rablock = (daddr64_t)lbn + 1; |
1c79356b | 266 | |
91447636 | 267 | if (ip->i_lastr + 1 == lbn && |
1c79356b | 268 | lblktosize(imp, rablock) < ip->i_size) { |
91447636 A |
269 | rasize = blksize(imp, ip, (daddr_t)rablock); |
270 | error = (int)buf_breadn(vp, (daddr64_t)((unsigned)lbn), size, &rablock, | |
1c79356b A |
271 | &rasize, 1, NOCRED, &bp); |
272 | } else | |
91447636 | 273 | error = (int)buf_bread(vp, (daddr64_t)((unsigned)lbn), size, NOCRED, &bp); |
1c79356b | 274 | |
91447636 A |
275 | ip->i_lastr = lbn; |
276 | n = min(n, size - buf_resid(bp)); | |
1c79356b | 277 | if (error) { |
91447636 | 278 | buf_brelse(bp); |
1c79356b A |
279 | return (error); |
280 | } | |
281 | ||
91447636 | 282 | error = uiomove((caddr_t)(buf_dataptr(bp) + on), (int)n, uio); |
1c79356b A |
283 | if (n + on == imp->logical_block_size || |
284 | uio->uio_offset == (off_t)ip->i_size) | |
91447636 A |
285 | buf_markaged(bp); |
286 | buf_brelse(bp); | |
287 | } while (error == 0 && uio_resid(uio) > 0 && n != 0); | |
1c79356b A |
288 | } |
289 | ||
290 | return (error); | |
291 | } | |
292 | ||
1c79356b | 293 | int |
91447636 | 294 | cd9660_ioctl(__unused struct vnop_ioctl_args *ap) |
1c79356b | 295 | { |
1c79356b A |
296 | return (ENOTTY); |
297 | } | |
298 | ||
1c79356b | 299 | int |
91447636 | 300 | cd9660_select(__unused struct vnop_select_args *ap) |
1c79356b A |
301 | { |
302 | /* | |
303 | * We should really check to see if I/O is possible. | |
304 | */ | |
305 | return (1); | |
306 | } | |
307 | ||
308 | /* | |
309 | * Mmap a file | |
310 | * | |
311 | * NB Currently unsupported. | |
312 | */ | |
1c79356b | 313 | int |
91447636 | 314 | cd9660_mmap(__unused struct vnop_mmap_args *ap) |
1c79356b A |
315 | { |
316 | ||
317 | return (EINVAL); | |
318 | } | |
319 | ||
1c79356b A |
320 | /* |
321 | * Structure for reading directories | |
322 | */ | |
323 | struct isoreaddir { | |
324 | struct dirent saveent; | |
325 | struct dirent current; | |
326 | off_t saveoff; | |
327 | off_t curroff; | |
328 | struct uio *uio; | |
329 | off_t uio_off; | |
330 | int eofflag; | |
331 | // u_long **cookies; | |
332 | // int *ncookies; | |
333 | }; | |
334 | ||
335 | static int | |
91447636 | 336 | iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off) |
1c79356b A |
337 | { |
338 | int error; | |
339 | ||
340 | dp->d_name[dp->d_namlen] = 0; | |
341 | dp->d_reclen = DIRSIZ(dp); | |
342 | ||
91447636 | 343 | if (uio_resid(idp->uio) < dp->d_reclen) { |
1c79356b A |
344 | idp->eofflag = 0; |
345 | return (-1); | |
346 | } | |
347 | ||
348 | #if 0 | |
349 | if (idp->cookies) { | |
350 | if (*idp->ncookies <= 0) { | |
351 | idp->eofflag = 0; | |
352 | return (-1); | |
353 | } | |
354 | ||
355 | **idp->cookies++ = off; | |
356 | --*idp->ncookies; | |
357 | } | |
358 | #endif | |
359 | ||
360 | if ( (error = uiomove( (caddr_t)dp, dp->d_reclen, idp->uio )) ) | |
361 | return (error); | |
362 | idp->uio_off = off; | |
363 | return (0); | |
364 | } | |
365 | ||
366 | static int | |
91447636 | 367 | iso_shipdir(struct isoreaddir *idp) |
1c79356b A |
368 | { |
369 | struct dirent *dp; | |
370 | int cl, sl; | |
371 | int error; | |
372 | char *cname, *sname; | |
373 | ||
374 | cl = idp->current.d_namlen; | |
375 | cname = idp->current.d_name; | |
376 | ||
377 | dp = &idp->saveent; | |
378 | sname = dp->d_name; | |
379 | sl = dp->d_namlen; | |
380 | if (sl > 0) { | |
381 | if (sl != cl | |
382 | || bcmp(sname,cname,sl)) { | |
383 | if (idp->saveent.d_namlen) { | |
384 | if ( (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) ) | |
385 | return (error); | |
386 | idp->saveent.d_namlen = 0; | |
387 | } | |
388 | } | |
389 | } | |
390 | idp->current.d_reclen = DIRSIZ(&idp->current); | |
391 | idp->saveoff = idp->curroff; | |
392 | bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); | |
393 | return (0); | |
394 | } | |
395 | ||
396 | /* | |
397 | * Vnode op for readdir | |
55e303ae A |
398 | * |
399 | * Note that directories are sector aligned (2K) and | |
400 | * that an entry can cross a logical block but not | |
401 | * a sector. | |
1c79356b A |
402 | */ |
403 | int | |
91447636 | 404 | cd9660_readdir(struct vnop_readdir_args *ap) |
1c79356b A |
405 | { |
406 | register struct uio *uio = ap->a_uio; | |
407 | off_t startingOffset = uio->uio_offset; | |
408 | size_t lost = 0; | |
409 | struct isoreaddir *idp; | |
410 | struct vnode *vdp = ap->a_vp; | |
411 | struct iso_node *dp; | |
412 | struct iso_mnt *imp; | |
413 | struct buf *bp = NULL; | |
414 | struct iso_directory_record *ep; | |
415 | int entryoffsetinblock; | |
416 | doff_t endsearch; | |
91447636 | 417 | uint32_t bmask; |
1c79356b A |
418 | int error = 0; |
419 | int reclen; | |
420 | u_short namelen; | |
421 | ||
91447636 A |
422 | if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF)) |
423 | return (EINVAL); | |
424 | ||
1c79356b A |
425 | dp = VTOI(vdp); |
426 | imp = dp->i_mnt; | |
55e303ae | 427 | bmask = imp->im_sector_size - 1; |
1c79356b A |
428 | |
429 | MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); | |
430 | idp->saveent.d_namlen = 0; | |
431 | /* | |
432 | * XXX | |
433 | * Is it worth trying to figure out the type? | |
434 | */ | |
435 | idp->saveent.d_type = idp->current.d_type = DT_UNKNOWN; | |
436 | idp->uio = uio; | |
437 | idp->eofflag = 1; | |
438 | idp->curroff = uio->uio_offset; | |
439 | ||
440 | if ((entryoffsetinblock = idp->curroff & bmask) && | |
91447636 | 441 | (error = cd9660_blkatoff(vdp, SECTOFF(imp, idp->curroff), NULL, &bp))) { |
1c79356b A |
442 | FREE(idp, M_TEMP); |
443 | return (error); | |
444 | } | |
445 | endsearch = dp->i_size; | |
446 | ||
447 | while (idp->curroff < endsearch) { | |
448 | /* | |
449 | * If offset is on a block boundary, | |
450 | * read the next directory block. | |
451 | * Release previous if it exists. | |
452 | */ | |
453 | if ((idp->curroff & bmask) == 0) { | |
454 | if (bp != NULL) | |
91447636 A |
455 | buf_brelse(bp); |
456 | if ((error = cd9660_blkatoff(vdp, SECTOFF(imp, idp->curroff), NULL, &bp))) | |
1c79356b A |
457 | break; |
458 | entryoffsetinblock = 0; | |
459 | } | |
460 | /* | |
461 | * Get pointer to next entry. | |
462 | */ | |
463 | ep = (struct iso_directory_record *) | |
91447636 | 464 | (buf_dataptr(bp) + entryoffsetinblock); |
1c79356b A |
465 | |
466 | reclen = isonum_711(ep->length); | |
467 | if (reclen == 0) { | |
468 | /* skip to next block, if any */ | |
469 | idp->curroff = | |
55e303ae | 470 | (idp->curroff & ~bmask) + imp->im_sector_size; |
1c79356b A |
471 | continue; |
472 | } | |
473 | ||
474 | if (reclen < ISO_DIRECTORY_RECORD_SIZE) { | |
475 | error = EINVAL; | |
476 | /* illegal entry, stop */ | |
477 | break; | |
478 | } | |
479 | ||
55e303ae | 480 | if (entryoffsetinblock + reclen > imp->im_sector_size) { |
1c79356b A |
481 | error = EINVAL; |
482 | /* illegal directory, so stop looking */ | |
483 | break; | |
484 | } | |
485 | ||
486 | idp->current.d_namlen = isonum_711(ep->name_len); | |
487 | ||
488 | if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { | |
489 | error = EINVAL; | |
490 | /* illegal entry, stop */ | |
491 | break; | |
492 | } | |
493 | ||
55e303ae A |
494 | /* |
495 | * Some poorly mastered discs have an incorrect directory | |
496 | * file size. If the '.' entry has a better size (bigger) | |
497 | * then use that instead. | |
498 | */ | |
499 | if ((uio->uio_offset == 0) && (isonum_733(ep->size) > endsearch)) { | |
500 | dp->i_size = endsearch = isonum_733(ep->size); | |
1c79356b A |
501 | } |
502 | ||
503 | if ( isonum_711(ep->flags) & directoryBit ) | |
504 | idp->current.d_fileno = isodirino(ep, imp); | |
505 | else { | |
91447636 | 506 | idp->current.d_fileno = ((daddr_t)buf_blkno(bp) << imp->im_bshift) + |
55e303ae | 507 | entryoffsetinblock; |
1c79356b A |
508 | } |
509 | ||
510 | idp->curroff += reclen; | |
511 | ||
512 | switch (imp->iso_ftype) { | |
513 | case ISO_FTYPE_RRIP: | |
514 | cd9660_rrip_getname(ep,idp->current.d_name, &namelen, | |
515 | &idp->current.d_fileno,imp); | |
516 | idp->current.d_namlen = (u_char)namelen; | |
517 | if (idp->current.d_namlen) | |
518 | error = iso_uiodir(idp,&idp->current,idp->curroff); | |
519 | break; | |
520 | ||
521 | case ISO_FTYPE_JOLIET: | |
522 | ucsfntrans((u_int16_t *)ep->name, idp->current.d_namlen, | |
523 | idp->current.d_name, &namelen, | |
55e303ae A |
524 | isonum_711(ep->flags) & directoryBit, |
525 | isonum_711(ep->flags) & associatedBit); | |
1c79356b A |
526 | idp->current.d_namlen = (u_char)namelen; |
527 | if (idp->current.d_namlen) | |
528 | error = iso_uiodir(idp,&idp->current,idp->curroff); | |
529 | break; | |
530 | ||
531 | default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ | |
532 | strcpy(idp->current.d_name,".."); | |
533 | switch (ep->name[0]) { | |
534 | case 0: | |
535 | idp->current.d_namlen = 1; | |
536 | error = iso_uiodir(idp,&idp->current,idp->curroff); | |
537 | break; | |
538 | case 1: | |
539 | idp->current.d_namlen = 2; | |
540 | error = iso_uiodir(idp,&idp->current,idp->curroff); | |
541 | break; | |
542 | default: | |
543 | isofntrans(ep->name,idp->current.d_namlen, | |
544 | idp->current.d_name, &namelen, | |
55e303ae A |
545 | imp->iso_ftype == ISO_FTYPE_9660, |
546 | isonum_711(ep->flags) & associatedBit); | |
1c79356b A |
547 | idp->current.d_namlen = (u_char)namelen; |
548 | if (imp->iso_ftype == ISO_FTYPE_DEFAULT) | |
549 | error = iso_shipdir(idp); | |
550 | else | |
551 | error = iso_uiodir(idp,&idp->current,idp->curroff); | |
552 | break; | |
553 | } | |
554 | } | |
555 | if (error) | |
556 | break; | |
557 | ||
558 | entryoffsetinblock += reclen; | |
559 | } | |
560 | ||
561 | if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { | |
562 | idp->current.d_namlen = 0; | |
563 | error = iso_shipdir(idp); | |
564 | } | |
91447636 | 565 | #if 0 |
1c79356b | 566 | if (!error && ap->a_ncookies) { |
91447636 | 567 | struct dirent *dirp, *dpstart; |
1c79356b A |
568 | off_t bufferOffset; |
569 | u_long *cookies; | |
570 | int ncookies; | |
571 | ||
572 | /* | |
573 | * Only the NFS server uses cookies, and it loads the | |
574 | * directory block into system space, so we can just look at | |
575 | * it directly. | |
576 | * | |
577 | * We assume the entire transfer is done to a single contiguous buffer. | |
578 | */ | |
91447636 | 579 | if (UIO_SEG_IS_USER_SPACE(uio->uio_segflg) || uio->uio_iovcnt != 1) |
1c79356b A |
580 | panic("ufs_readdir: lost in space"); |
581 | ||
582 | /* | |
583 | * Make a first pass over the buffer just generated, | |
584 | * counting the number of entries: | |
585 | */ | |
91447636 A |
586 | // LP64todo - fix this! |
587 | dpstart = (struct dirent *) | |
588 | CAST_DOWN(caddr_t, (uio_iov_base(uio) - (uio->uio_offset - startingOffset))); | |
589 | for (dirp = dpstart, bufferOffset = startingOffset, ncookies = 0; | |
1c79356b | 590 | bufferOffset < uio->uio_offset; ) { |
91447636 | 591 | if (dirp->d_reclen == 0) |
1c79356b | 592 | break; |
91447636 | 593 | bufferOffset += dirp->d_reclen; |
1c79356b | 594 | ncookies++; |
91447636 | 595 | dirp = (struct dirent *)((caddr_t)dirp + dirp->d_reclen); |
1c79356b A |
596 | } |
597 | lost += uio->uio_offset - bufferOffset; | |
598 | uio->uio_offset = bufferOffset; | |
599 | ||
600 | /* | |
601 | * Allocate a buffer to hold the cookies requested: | |
602 | */ | |
603 | MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK); | |
604 | *ap->a_ncookies = ncookies; | |
605 | *ap->a_cookies = cookies; | |
606 | ||
607 | /* | |
608 | * Fill in the offsets for each entry in the buffer just allocated: | |
609 | */ | |
91447636 | 610 | for (bufferOffset = startingOffset, dirp = dpstart; bufferOffset < uio->uio_offset; ) { |
1c79356b | 611 | *(cookies++) = bufferOffset; |
91447636 A |
612 | bufferOffset += dirp->d_reclen; |
613 | dirp = (struct dirent *)((caddr_t)dirp + dirp->d_reclen); | |
1c79356b A |
614 | } |
615 | } | |
91447636 | 616 | #endif |
1c79356b A |
617 | if (error < 0) |
618 | error = 0; | |
619 | ||
620 | if (bp) | |
91447636 | 621 | buf_brelse (bp); |
1c79356b A |
622 | |
623 | uio->uio_offset = idp->uio_off; | |
624 | *ap->a_eofflag = idp->eofflag; | |
625 | ||
626 | FREE(idp, M_TEMP); | |
627 | ||
628 | return (error); | |
629 | } | |
630 | ||
631 | /* | |
632 | * Return target name of a symbolic link | |
633 | * Shouldn't we get the parent vnode and read the data from there? | |
634 | * This could eventually result in deadlocks in cd9660_lookup. | |
635 | * But otherwise the block read here is in the block buffer two times. | |
636 | */ | |
637 | typedef struct iso_directory_record ISODIR; | |
638 | typedef struct iso_node ISONODE; | |
639 | typedef struct iso_mnt ISOMNT; | |
640 | int | |
91447636 | 641 | cd9660_readlink(struct vnop_readlink_args *ap) |
1c79356b A |
642 | { |
643 | ISONODE *ip; | |
644 | ISODIR *dirp; | |
645 | ISOMNT *imp; | |
646 | struct buf *bp; | |
647 | struct uio *uio; | |
648 | u_short symlen; | |
649 | int error; | |
650 | char *symname; | |
651 | ||
652 | ip = VTOI(ap->a_vp); | |
653 | imp = ip->i_mnt; | |
654 | uio = ap->a_uio; | |
655 | ||
656 | if (imp->iso_ftype != ISO_FTYPE_RRIP) | |
657 | return (EINVAL); | |
658 | ||
659 | /* | |
660 | * Get parents directory record block that this inode included. | |
661 | */ | |
91447636 A |
662 | error = (int)buf_bread(imp->im_devvp, |
663 | (daddr64_t)((unsigned)(ip->i_number >> imp->im_bshift)), | |
1c79356b A |
664 | imp->logical_block_size, NOCRED, &bp); |
665 | if (error) { | |
91447636 | 666 | buf_brelse(bp); |
1c79356b A |
667 | return (EINVAL); |
668 | } | |
669 | ||
670 | /* | |
671 | * Setup the directory pointer for this inode | |
672 | */ | |
91447636 | 673 | dirp = (ISODIR *)(buf_dataptr(bp) + (ip->i_number & imp->im_bmask)); |
1c79356b A |
674 | |
675 | /* | |
676 | * Just make sure, we have a right one.... | |
677 | * 1: Check not cross boundary on block | |
678 | */ | |
679 | if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) | |
680 | > imp->logical_block_size) { | |
91447636 | 681 | buf_brelse(bp); |
1c79356b A |
682 | return (EINVAL); |
683 | } | |
684 | ||
685 | /* | |
686 | * Now get a buffer | |
687 | * Abuse a namei buffer for now. | |
688 | */ | |
91447636 | 689 | if (UIO_SEG_IS_USER_SPACE(uio->uio_segflg)) |
1c79356b | 690 | MALLOC_ZONE(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); |
91447636 A |
691 | else |
692 | // LP64todo - fix this! | |
693 | symname = CAST_DOWN(caddr_t, uio_iov_base(uio)); | |
1c79356b A |
694 | |
695 | /* | |
696 | * Ok, we just gathering a symbolic name in SL record. | |
697 | */ | |
698 | if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { | |
91447636 | 699 | if (UIO_SEG_IS_USER_SPACE(uio->uio_segflg)) |
1c79356b | 700 | FREE_ZONE(symname, MAXPATHLEN, M_NAMEI); |
91447636 | 701 | buf_brelse(bp); |
1c79356b A |
702 | return (EINVAL); |
703 | } | |
704 | /* | |
705 | * Don't forget before you leave from home ;-) | |
706 | */ | |
91447636 | 707 | buf_brelse(bp); |
1c79356b A |
708 | |
709 | /* | |
710 | * return with the symbolic name to caller's. | |
711 | */ | |
91447636 | 712 | if (UIO_SEG_IS_USER_SPACE(uio->uio_segflg)) { |
1c79356b A |
713 | error = uiomove(symname, symlen, uio); |
714 | FREE_ZONE(symname, MAXPATHLEN, M_NAMEI); | |
715 | return (error); | |
716 | } | |
91447636 A |
717 | #if LP64KERN |
718 | uio_setresid(uio, (uio_resid(uio) - symlen)); | |
719 | uio_iov_len_add(uio, -((int64_t)symlen)); | |
720 | #else | |
721 | uio_setresid(uio, (uio_resid(uio) - symlen)); | |
722 | uio_iov_len_add(uio, -((int)symlen)); | |
723 | #endif | |
724 | uio_iov_base_add(uio, symlen); | |
1c79356b A |
725 | return (0); |
726 | } | |
727 | ||
1c79356b A |
728 | |
729 | /* | |
91447636 | 730 | * prepare and issue the I/O |
1c79356b A |
731 | */ |
732 | int | |
91447636 | 733 | cd9660_strategy(struct vnop_strategy_args *ap) |
1c79356b | 734 | { |
91447636 A |
735 | buf_t bp = ap->a_bp; |
736 | vnode_t vp = buf_vnode(bp); | |
737 | struct iso_node *ip = VTOI(vp); | |
1c79356b | 738 | |
91447636 | 739 | return (buf_strategy(ip->i_devvp, ap)); |
1c79356b A |
740 | } |
741 | ||
1c79356b A |
742 | |
743 | /* | |
744 | * Return POSIX pathconf information applicable to cd9660 filesystems. | |
745 | */ | |
746 | int | |
91447636 | 747 | cd9660_pathconf(struct vnop_pathconf_args *ap) |
1c79356b A |
748 | { |
749 | ||
750 | switch (ap->a_name) { | |
751 | case _PC_LINK_MAX: | |
752 | *ap->a_retval = 1; | |
753 | return (0); | |
754 | case _PC_NAME_MAX: | |
755 | switch (VTOI(ap->a_vp)->i_mnt->iso_ftype) { | |
756 | case ISO_FTYPE_RRIP: | |
757 | *ap->a_retval = ISO_RRIP_NAMEMAX; | |
758 | break; | |
759 | case ISO_FTYPE_JOLIET: | |
760 | *ap->a_retval = ISO_JOLIET_NAMEMAX; | |
761 | break; | |
762 | default: | |
763 | *ap->a_retval = ISO_NAMEMAX; | |
764 | } | |
765 | return (0); | |
766 | case _PC_PATH_MAX: | |
767 | *ap->a_retval = PATH_MAX; | |
768 | return (0); | |
769 | case _PC_PIPE_BUF: | |
770 | *ap->a_retval = PIPE_BUF; | |
771 | return (0); | |
772 | case _PC_CHOWN_RESTRICTED: | |
773 | *ap->a_retval = 1; | |
774 | return (0); | |
775 | case _PC_NO_TRUNC: | |
776 | *ap->a_retval = 1; | |
777 | return (0); | |
778 | default: | |
779 | return (EINVAL); | |
780 | } | |
781 | /* NOTREACHED */ | |
782 | } | |
783 | ||
784 | /* | |
785 | * Unsupported operation | |
786 | */ | |
787 | int | |
91447636 | 788 | cd9660_enotsupp(void) |
1c79356b | 789 | { |
91447636 | 790 | return (ENOTSUP); |
1c79356b A |
791 | } |
792 | /* Pagein. similar to read */ | |
793 | int | |
91447636 | 794 | cd9660_pagein(struct vnop_pagein_args *ap) |
1c79356b A |
795 | { |
796 | struct vnode *vp = ap->a_vp; | |
797 | upl_t pl = ap->a_pl; | |
55e303ae | 798 | size_t size = ap->a_size; |
1c79356b A |
799 | off_t f_offset = ap->a_f_offset; |
800 | vm_offset_t pl_offset = ap->a_pl_offset; | |
801 | int flags = ap->a_flags; | |
802 | register struct iso_node *ip = VTOI(vp); | |
55e303ae | 803 | int error = 0; |
1c79356b | 804 | |
55e303ae A |
805 | /* |
806 | * Copy the Apple Double header. | |
807 | */ | |
808 | if ((ip->i_flag & ISO_ASSOCIATED) && (f_offset == 0) && (size == ADH_SIZE)) { | |
809 | apple_double_header_t header; | |
810 | kern_return_t kret; | |
811 | vm_offset_t ioaddr; | |
812 | ||
813 | kret = ubc_upl_map(pl, &ioaddr); | |
814 | if (kret != KERN_SUCCESS) | |
815 | panic("cd9660_xa_pagein: ubc_upl_map error = %d", kret); | |
816 | ioaddr += pl_offset; | |
817 | bzero((caddr_t)ioaddr, ADH_SIZE); | |
818 | ||
819 | header.magic = APPLEDOUBLE_MAGIC; | |
820 | header.version = APPLEDOUBLE_VERSION; | |
821 | header.count = 2; | |
822 | header.entries[0].entryID = APPLEDOUBLE_FINDERINFO; | |
823 | header.entries[0].offset = offsetof(apple_double_header_t, finfo); | |
824 | header.entries[0].length = 32; | |
825 | header.entries[1].entryID = APPLEDOUBLE_RESFORK; | |
826 | header.entries[1].offset = ADH_SIZE; | |
827 | header.entries[1].length = ip->i_size - ADH_SIZE; | |
828 | header.finfo.fdType = ip->i_FileType; | |
829 | header.finfo.fdCreator = ip->i_Creator; | |
830 | header.finfo.fdFlags = ip->i_FinderFlags; | |
831 | header.finfo.fdLocation.v = -1; | |
832 | header.finfo.fdLocation.h = -1; | |
833 | header.finfo.fdReserved = 0; | |
834 | ||
835 | bcopy((caddr_t)&header, (caddr_t)ioaddr, sizeof(apple_double_header_t)); | |
836 | ||
837 | kret = ubc_upl_unmap(pl); | |
838 | if (kret != KERN_SUCCESS) | |
839 | panic("cd9660_xa_pagein: ubc_upl_unmap error = %d", kret); | |
840 | ||
841 | if ((flags & UPL_NOCOMMIT) == 0) { | |
842 | ubc_upl_commit_range(pl, pl_offset, size, UPL_COMMIT_FREE_ON_EMPTY); | |
843 | } | |
844 | } else { | |
55e303ae A |
845 | /* check pageouts are for reg file only and ubc info is present*/ |
846 | if (UBCINVALID(vp)) | |
847 | panic("cd9660_pagein: Not a VREG"); | |
848 | UBCINFOCHECK("cd9660_pagein", vp); | |
849 | ||
55e303ae | 850 | error = cluster_pagein(vp, pl, pl_offset, f_offset, size, |
91447636 | 851 | (off_t)ip->i_size, flags); |
55e303ae | 852 | } |
1c79356b A |
853 | return (error); |
854 | } | |
855 | ||
856 | /* | |
857 | * cd9660_remove - not possible to remove a file from iso cds | |
858 | * | |
859 | * Locking policy: a_dvp and vp locked on entry, unlocked on exit | |
860 | */ | |
861 | int | |
91447636 | 862 | cd9660_remove(__unused struct vnop_remove_args *ap) |
1c79356b | 863 | { |
1c79356b A |
864 | return (EROFS); |
865 | } | |
866 | ||
867 | ||
868 | /* | |
869 | * cd9660_rmdir - not possible to remove a directory from iso cds | |
870 | * | |
871 | * Locking policy: a_dvp and vp locked on entry, unlocked on exit | |
872 | */ | |
873 | int | |
91447636 | 874 | cd9660_rmdir(struct vnop_rmdir_args *ap) |
1c79356b A |
875 | { |
876 | (void) nop_rmdir(ap); | |
877 | return (EROFS); | |
878 | } | |
879 | ||
880 | /* | |
881 | ||
882 | # | |
883 | #% getattrlist vp = = = | |
884 | # | |
91447636 | 885 | vnop_getattrlist { |
1c79356b A |
886 | IN struct vnode *vp; |
887 | IN struct attrlist *alist; | |
888 | INOUT struct uio *uio; | |
91447636 | 889 | IN vfs_context_t context; |
1c79356b A |
890 | }; |
891 | ||
892 | */ | |
893 | int | |
91447636 | 894 | cd9660_getattrlist(struct vnop_getattrlist_args *ap) |
1c79356b A |
895 | { |
896 | struct attrlist *alist = ap->a_alist; | |
897 | int fixedblocksize; | |
898 | int attrblocksize; | |
899 | int attrbufsize; | |
900 | void *attrbufptr; | |
901 | void *attrptr; | |
902 | void *varptr; | |
903 | int error = 0; | |
904 | ||
905 | if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) || | |
906 | ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) || | |
907 | ((alist->volattr & ~ATTR_VOL_VALIDMASK) != 0) || | |
908 | ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) || | |
909 | ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0) || | |
910 | ((alist->forkattr & ~ATTR_FORK_VALIDMASK) != 0)) { | |
911 | return EINVAL; | |
912 | }; | |
913 | ||
914 | /* | |
915 | * Requesting volume information requires setting the ATTR_VOL_INFO bit and | |
916 | * volume info requests are mutually exclusive with all other info requests: | |
917 | */ | |
918 | if ((alist->volattr != 0) && | |
919 | (((alist->volattr & ATTR_VOL_INFO) == 0) || | |
920 | (alist->dirattr != 0) || | |
921 | (alist->fileattr != 0) || | |
922 | (alist->forkattr != 0) )) { | |
923 | return EINVAL; | |
924 | }; | |
925 | ||
926 | /* | |
927 | * Reject requests for unsupported options for now: | |
928 | */ | |
929 | if (alist->volattr & ATTR_VOL_MOUNTPOINT) return EINVAL; | |
930 | if (alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST)) return EINVAL; | |
931 | if (alist->fileattr & | |
932 | (ATTR_FILE_FILETYPE | | |
933 | ATTR_FILE_FORKCOUNT | | |
934 | ATTR_FILE_FORKLIST | | |
935 | ATTR_FILE_DATAEXTENTS | | |
936 | ATTR_FILE_RSRCEXTENTS)) { | |
937 | return EINVAL; | |
938 | }; | |
939 | ||
940 | ||
941 | fixedblocksize = attrcalcsize(alist); | |
91447636 | 942 | attrblocksize = fixedblocksize + (sizeof(uint32_t)); /* uint32_t for length word */ |
1c79356b A |
943 | if (alist->commonattr & ATTR_CMN_NAME) attrblocksize += NAME_MAX; |
944 | if (alist->commonattr & ATTR_CMN_NAMEDATTRLIST) attrblocksize += 0; /* XXX PPD */ | |
945 | if (alist->volattr & ATTR_VOL_MOUNTPOINT) attrblocksize += PATH_MAX; | |
946 | if (alist->volattr & ATTR_VOL_NAME) attrblocksize += NAME_MAX; | |
947 | if (alist->fileattr & ATTR_FILE_FORKLIST) attrblocksize += 0; /* XXX PPD */ | |
948 | ||
91447636 | 949 | attrbufsize = MIN(uio_resid(ap->a_uio), attrblocksize); |
1c79356b A |
950 | MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK); |
951 | attrptr = attrbufptr; | |
91447636 A |
952 | *((uint32_t *)attrptr) = 0; /* Set buffer length in case of errors */ |
953 | ++((uint32_t *)attrptr); /* Reserve space for length field */ | |
1c79356b A |
954 | varptr = ((char *)attrptr) + fixedblocksize; /* Point to variable-length storage */ |
955 | ||
956 | packattrblk(alist, ap->a_vp, &attrptr, &varptr); | |
957 | ||
958 | /* Store length of fixed + var block */ | |
91447636 | 959 | *((uint32_t *)attrbufptr) = ((char*)varptr - (char*)attrbufptr); |
1c79356b A |
960 | /* Don't copy out more data than was generated */ |
961 | attrbufsize = MIN(attrbufsize, (char*)varptr - (char*)attrbufptr); | |
962 | ||
963 | error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio); | |
964 | ||
965 | FREE(attrbufptr, M_TEMP); | |
966 | ||
967 | return error; | |
968 | } | |
969 | ||
55e303ae A |
970 | /* |
971 | * Make a RIFF file header for a CD-ROM XA media file. | |
972 | */ | |
973 | __private_extern__ void | |
91447636 | 974 | cd9660_xa_init(struct iso_node *ip, struct iso_directory_record *isodir) |
55e303ae | 975 | { |
91447636 | 976 | uint32_t sectors; |
55e303ae A |
977 | struct riff_header *header; |
978 | u_char name_len; | |
979 | char *cdxa; | |
980 | ||
981 | MALLOC(header, struct riff_header *, sizeof(struct riff_header), M_TEMP, M_WAITOK); | |
982 | ||
983 | sectors = ip->i_size / 2048; | |
984 | ||
985 | strncpy(header->riff, "RIFF", 4); | |
8ad349bb | 986 | header->fileSize = NXSwapHostLongToLittle(sectors * CDXA_SECTOR_SIZE + sizeof(struct riff_header) - 8); |
55e303ae A |
987 | strncpy(header->cdxa, "CDXA", 4); |
988 | strncpy(header->fmt, "fmt ", 4); | |
8ad349bb | 989 | header->fmtSize = NXSwapHostLongToLittle(16); |
55e303ae | 990 | strncpy(header->data, "data", 4); |
8ad349bb | 991 | header->dataSize = NXSwapHostLongToLittle(sectors * CDXA_SECTOR_SIZE); |
55e303ae A |
992 | |
993 | /* | |
994 | * Copy the CD-ROM XA extended directory information into the header. As far as | |
995 | * I can tell, it's always 14 bytes in the directory record, but allocated 16 bytes | |
996 | * in the header (the last two being zeroed pad bytes). | |
997 | */ | |
998 | name_len = isonum_711(isodir->name_len); | |
999 | cdxa = &isodir->name[name_len]; | |
1000 | if ((name_len & 0x01) == 0) | |
1001 | ++cdxa; /* Skip pad byte */ | |
1002 | bcopy(cdxa, header->fmtData, 14); | |
1003 | header->fmtData[14] = 0; | |
1004 | header->fmtData[15] = 0; | |
1005 | ||
1006 | /* | |
1007 | * Point this i-node to the "whole sector" device instead of the normal | |
1008 | * device. This allows cd9660_strategy to be ignorant of the block | |
1009 | * (sector) size. | |
1010 | */ | |
55e303ae | 1011 | ip->i_devvp = ip->i_mnt->phys_devvp; |
55e303ae A |
1012 | |
1013 | ip->i_size = sectors * CDXA_SECTOR_SIZE + sizeof(struct riff_header); | |
1014 | ip->i_riff = header; | |
55e303ae A |
1015 | } |
1016 | ||
1017 | /* | |
91447636 | 1018 | * Helper routine for vnop_read and vnop_pagein of CD-ROM XA multimedia files. |
55e303ae A |
1019 | * This routine determines the physical location of the file, then reads |
1020 | * sectors directly from the device into a buffer. It also handles inserting | |
1021 | * the RIFF header at the beginning of the file. | |
1022 | * | |
1023 | * Exactly one of buffer or uio must be non-zero. It will either bcopy to | |
1024 | * buffer, or uiomove via uio. | |
1025 | * | |
91447636 | 1026 | * XXX Should this code be using buf_breadn and ip->i_lastr to support single-block |
55e303ae A |
1027 | * read-ahead? Should we try more aggressive read-ahead like cluster_io does? |
1028 | * | |
1029 | * XXX This could be made to do larger I/O to the device (reading all the | |
1030 | * whole sectors directly into the buffer). That would make the code more | |
1031 | * complex, and the current code only adds 2.5% overhead compared to reading | |
1032 | * from the device directly (at least on my test machine). | |
1033 | */ | |
1034 | static int | |
1035 | cd9660_xa_read_common( | |
1036 | struct vnode *vp, | |
1037 | off_t offset, | |
1038 | size_t amount, | |
1039 | caddr_t buffer, | |
1040 | struct uio *uio) | |
1041 | { | |
1042 | struct iso_node *ip = VTOI(vp); | |
1043 | struct buf *bp; | |
1044 | off_t diff; /* number of bytes from offset to file's EOF */ | |
1045 | daddr_t block; /* physical disk block containing offset */ | |
1046 | off_t sect_off; /* starting offset into current sector */ | |
1047 | u_int count; /* number of bytes to transfer in current block */ | |
1048 | int error=0; | |
1049 | ||
1050 | /* | |
1051 | * Copy any part of the RIFF header. | |
1052 | */ | |
1053 | if (offset < sizeof(struct riff_header)) { | |
1054 | char *p; | |
1055 | ||
1056 | p = ((char *) ip->i_riff) + offset; | |
1057 | count = min(amount, sizeof(struct riff_header) - offset); | |
1058 | if (buffer) { | |
1059 | bcopy(p, buffer, count); | |
1060 | buffer += count; | |
1061 | } else { | |
1062 | error = uiomove(p, count, uio); | |
1063 | } | |
1064 | amount -= count; | |
1065 | offset += count; | |
1066 | } | |
1067 | if (error) | |
1068 | return error; | |
1069 | ||
1070 | /* | |
1071 | * Loop over (possibly partial) blocks to transfer. | |
1072 | */ | |
1073 | while (error == 0 && amount > 0) { | |
1074 | /* | |
1075 | * Determine number of bytes until EOF. If we've hit | |
1076 | * EOF then return. | |
1077 | */ | |
1078 | diff = ip->i_size - offset; | |
1079 | if (diff <= 0) | |
1080 | return 0; | |
1081 | ||
1082 | /* Get a block from the underlying device */ | |
1083 | block = ip->iso_start + (offset - sizeof(struct riff_header))/CDXA_SECTOR_SIZE; | |
91447636 | 1084 | error = (int)buf_bread(ip->i_devvp, (daddr64_t)((unsigned)block), CDXA_SECTOR_SIZE, NOCRED, &bp); |
55e303ae | 1085 | if (error) { |
91447636 | 1086 | buf_brelse(bp); |
55e303ae A |
1087 | return error; |
1088 | } | |
91447636 A |
1089 | if (buf_resid(bp)) { |
1090 | printf("isofs: cd9660_xa_read_common: buf_bread didn't read full sector\n"); | |
55e303ae A |
1091 | return EIO; |
1092 | } | |
1093 | ||
1094 | /* Figure out which part of the block to copy, and copy it */ | |
1095 | sect_off = (offset - sizeof(struct riff_header)) % CDXA_SECTOR_SIZE; | |
1096 | count = min(CDXA_SECTOR_SIZE-sect_off, amount); | |
1097 | if (diff < count) /* Pin transfer amount to EOF */ | |
1098 | count = diff; | |
1099 | ||
1100 | if (buffer) { | |
91447636 | 1101 | bcopy(CAST_DOWN(caddr_t, (buf_dataptr(bp)+sect_off)), buffer, count); |
55e303ae A |
1102 | buffer += count; |
1103 | } else { | |
91447636 | 1104 | error = uiomove(CAST_DOWN(caddr_t, (buf_dataptr(bp)+sect_off)), count, uio); |
55e303ae A |
1105 | } |
1106 | amount -= count; | |
1107 | offset += count; | |
1108 | ||
1109 | /* | |
1110 | * If we copied through the end of the block, or the end of file, then | |
1111 | * age the device block. This is optimized for sequential access. | |
1112 | */ | |
1113 | if (sect_off+count == CDXA_SECTOR_SIZE || offset == (off_t)ip->i_size) | |
91447636 A |
1114 | buf_markaged(bp); |
1115 | buf_brelse(bp); | |
55e303ae A |
1116 | } |
1117 | ||
1118 | return error; | |
1119 | } | |
1120 | ||
1121 | /* | |
1122 | * Read from a CD-ROM XA multimedia file. | |
1123 | * | |
1124 | * This uses the same common routine as pagein for doing the actual read | |
1125 | * from the device. | |
1126 | * | |
1127 | * This routine doesn't do any caching beyond what the block device does. | |
1128 | * Even then, cd9660_xa_read_common ages the blocks once we read up to | |
1129 | * the end. | |
1130 | * | |
1131 | * We don't even take advantage if the file has been memory mapped and has | |
1132 | * valid pages already (in which case we could just uiomove from the page | |
1133 | * to the caller). Since we're a read-only filesystem, there can't be | |
1134 | * any cache coherency problems. Multimedia files are expected to be | |
1135 | * large and streamed anyway, so caching file contents probably isn't | |
1136 | * important. | |
1137 | */ | |
1138 | int | |
91447636 | 1139 | cd9660_xa_read(struct vnop_read_args *ap) |
55e303ae A |
1140 | { |
1141 | struct vnode *vp = ap->a_vp; | |
1142 | register struct uio *uio = ap->a_uio; | |
1143 | register struct iso_node *ip = VTOI(vp); | |
1144 | off_t offset = uio->uio_offset; | |
91447636 A |
1145 | // LP64todo - fix this! |
1146 | size_t size = uio_resid(uio); | |
55e303ae A |
1147 | |
1148 | /* Check for some obvious parameter problems */ | |
1149 | if (offset < 0) | |
1150 | return EINVAL; | |
1151 | if (size == 0) | |
1152 | return 0; | |
1153 | if (offset >= ip->i_size) | |
1154 | return 0; | |
1155 | ||
1156 | /* Pin the size of the read to the file's EOF */ | |
1157 | if (offset + size > ip->i_size) | |
1158 | size = ip->i_size - offset; | |
1159 | ||
1160 | return cd9660_xa_read_common(vp, offset, size, NULL, uio); | |
1161 | } | |
1162 | ||
1163 | /* | |
1164 | * Page in from a CD-ROM XA media file. | |
1165 | * | |
1166 | * Since our device block size isn't a power of two, we can't use | |
1167 | * cluster_pagein. Instead, we have to map the page and read into it. | |
1168 | */ | |
1169 | static int | |
91447636 | 1170 | cd9660_xa_pagein(struct vnop_pagein_args *ap) |
55e303ae A |
1171 | { |
1172 | struct vnode *vp = ap->a_vp; | |
1173 | upl_t pl = ap->a_pl; | |
1174 | size_t size= ap->a_size; | |
1175 | off_t f_offset = ap->a_f_offset; | |
1176 | vm_offset_t pl_offset = ap->a_pl_offset; | |
1177 | int flags = ap->a_flags; | |
1178 | register struct iso_node *ip = VTOI(vp); | |
1179 | int error; | |
1180 | kern_return_t kret; | |
1181 | vm_offset_t ioaddr; | |
1182 | ||
1183 | /* check pageins are for reg file only and ubc info is present*/ | |
1184 | if (UBCINVALID(vp)) | |
1185 | panic("cd9660_xa_pagein: Not a VREG"); | |
1186 | UBCINFOCHECK("cd9660_xa_pagein", vp); | |
1187 | ||
1188 | if (size <= 0) | |
1189 | panic("cd9660_xa_pagein: size = %d", size); | |
1190 | ||
1191 | kret = ubc_upl_map(pl, &ioaddr); | |
1192 | if (kret != KERN_SUCCESS) | |
1193 | panic("cd9660_xa_pagein: ubc_upl_map error = %d", kret); | |
1194 | ||
1195 | ioaddr += pl_offset; | |
1196 | ||
1197 | /* Make sure pagein doesn't extend past EOF */ | |
1198 | if (f_offset + size > ip->i_size) | |
1199 | size = ip->i_size - f_offset; /* pin size to EOF */ | |
1200 | ||
1201 | /* Read the data in using the underlying device */ | |
1202 | error = cd9660_xa_read_common(vp, f_offset, size, (caddr_t)ioaddr, NULL); | |
1203 | ||
1204 | /* Zero fill part of page past EOF */ | |
1205 | if (ap->a_size > size) | |
1206 | bzero((caddr_t)ioaddr+size, ap->a_size-size); | |
1207 | ||
1208 | kret = ubc_upl_unmap(pl); | |
1209 | if (kret != KERN_SUCCESS) | |
1210 | panic("cd9660_xa_pagein: ubc_upl_unmap error = %d", kret); | |
1211 | ||
1212 | if ((flags & UPL_NOCOMMIT) == 0) | |
1213 | { | |
1214 | if (error) | |
1215 | ubc_upl_abort_range(pl, pl_offset, ap->a_size, UPL_ABORT_FREE_ON_EMPTY); | |
1216 | else | |
1217 | ubc_upl_commit_range(pl, pl_offset, ap->a_size, UPL_COMMIT_FREE_ON_EMPTY); | |
1218 | } | |
1219 | ||
1220 | return error; | |
1221 | } | |
1222 | ||
1c79356b A |
1223 | /* |
1224 | * Global vfs data structures for isofs | |
1225 | */ | |
1226 | #define cd9660_create \ | |
91447636 A |
1227 | ((int (*)(struct vnop_create_args *))err_create) |
1228 | #define cd9660_mknod ((int (*)(struct vnop_mknod_args *))err_mknod) | |
1229 | #define cd9660_write ((int (*)(struct vnop_write_args *))cd9660_enotsupp) | |
1230 | #define cd9660_fsync ((int (*)(struct vnop_fsync_args *))nullop) | |
1c79356b | 1231 | #define cd9660_rename \ |
91447636 | 1232 | ((int (*)(struct vnop_rename_args *))err_rename) |
1c79356b | 1233 | #define cd9660_copyfile \ |
91447636 A |
1234 | ((int (*)(struct vnop_copyfile_args *))err_copyfile) |
1235 | #define cd9660_link ((int (*)(struct vnop_link_args *))err_link) | |
1236 | #define cd9660_mkdir ((int (*)(struct vnop_mkdir_args *))err_mkdir) | |
1c79356b | 1237 | #define cd9660_symlink \ |
91447636 | 1238 | ((int (*)(struct vnop_symlink_args *))err_symlink) |
1c79356b | 1239 | #define cd9660_advlock \ |
91447636 | 1240 | ((int (*)(struct vnop_advlock_args *))cd9660_enotsupp) |
1c79356b | 1241 | #define cd9660_bwrite \ |
91447636 | 1242 | ((int (*)(struct vnop_bwrite_args *))cd9660_enotsupp) |
1c79356b | 1243 | #define cd9660_pageout \ |
91447636 A |
1244 | ((int (*)(struct vnop_pageout_args *))cd9660_enotsupp) |
1245 | int cd9660_blktooff(struct vnop_blktooff_args *ap); | |
1246 | int cd9660_offtoblk(struct vnop_offtoblk_args *ap); | |
1247 | int cd9660_blockmap(struct vnop_blockmap_args *ap); | |
1c79356b A |
1248 | |
1249 | #define VOPFUNC int (*)(void *) | |
1250 | /* | |
1251 | * Global vfs data structures for cd9660 | |
1252 | */ | |
1253 | int (**cd9660_vnodeop_p)(void *); | |
1254 | struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { | |
91447636 A |
1255 | { &vnop_default_desc, (VOPFUNC)vn_default_error }, |
1256 | { &vnop_lookup_desc, (VOPFUNC)cd9660_lookup }, /* lookup */ | |
1257 | { &vnop_create_desc, (VOPFUNC)cd9660_create }, /* create */ | |
1258 | { &vnop_mknod_desc, (VOPFUNC)cd9660_mknod }, /* mknod */ | |
1259 | { &vnop_open_desc, (VOPFUNC)cd9660_open }, /* open */ | |
1260 | { &vnop_close_desc, (VOPFUNC)cd9660_close }, /* close */ | |
1261 | { &vnop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */ | |
1262 | { &vnop_read_desc, (VOPFUNC)cd9660_read }, /* read */ | |
1263 | { &vnop_write_desc, (VOPFUNC)cd9660_write }, /* write */ | |
1264 | { &vnop_ioctl_desc, (VOPFUNC)cd9660_ioctl }, /* ioctl */ | |
1265 | { &vnop_select_desc, (VOPFUNC)cd9660_select }, /* select */ | |
1266 | { &vnop_mmap_desc, (VOPFUNC)cd9660_mmap }, /* mmap */ | |
1267 | { &vnop_fsync_desc, (VOPFUNC)cd9660_fsync }, /* fsync */ | |
1268 | { &vnop_remove_desc, (VOPFUNC)cd9660_remove }, /* remove */ | |
1269 | { &vnop_link_desc, (VOPFUNC)cd9660_link }, /* link */ | |
1270 | { &vnop_rename_desc, (VOPFUNC)cd9660_rename }, /* rename */ | |
1271 | { &vnop_copyfile_desc, (VOPFUNC)cd9660_copyfile },/* copyfile */ | |
1272 | { &vnop_mkdir_desc, (VOPFUNC)cd9660_mkdir }, /* mkdir */ | |
1273 | { &vnop_rmdir_desc, (VOPFUNC)cd9660_rmdir }, /* rmdir */ | |
1274 | { &vnop_symlink_desc, (VOPFUNC)cd9660_symlink }, /* symlink */ | |
1275 | { &vnop_readdir_desc, (VOPFUNC)cd9660_readdir }, /* readdir */ | |
1276 | { &vnop_readlink_desc, (VOPFUNC)cd9660_readlink },/* readlink */ | |
1277 | { &vnop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */ | |
1278 | { &vnop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */ | |
1279 | { &vnop_strategy_desc, (VOPFUNC)cd9660_strategy },/* strategy */ | |
1280 | { &vnop_pathconf_desc, (VOPFUNC)cd9660_pathconf },/* pathconf */ | |
1281 | { &vnop_advlock_desc, (VOPFUNC)cd9660_advlock }, /* advlock */ | |
1282 | { &vnop_bwrite_desc, (VOPFUNC)vn_bwrite }, | |
1283 | { &vnop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */ | |
1284 | { &vnop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */ | |
1285 | { &vnop_getattrlist_desc, (VOPFUNC)cd9660_getattrlist }, /* getattrlist */ | |
1286 | { &vnop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */ | |
1287 | { &vnop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */ | |
1288 | { &vnop_blockmap_desc, (VOPFUNC)cd9660_blockmap }, /* blockmap */ | |
1c79356b A |
1289 | { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL } |
1290 | }; | |
1291 | struct vnodeopv_desc cd9660_vnodeop_opv_desc = | |
1292 | { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; | |
1293 | ||
55e303ae A |
1294 | /* |
1295 | * The VOP table for CD-ROM XA (media) files is almost the same | |
1296 | * as for ordinary files, except for read, and pagein. | |
91447636 | 1297 | * Note that cd9660_xa_read doesn't use cluster I/O, so blockmap |
55e303ae | 1298 | * isn't needed, and isn't implemented. Similarly, it doesn't |
91447636 | 1299 | * do buf_bread() on CD XA vnodes, so bmap, blktooff, offtoblk |
55e303ae A |
1300 | * aren't needed. |
1301 | */ | |
1302 | int (**cd9660_cdxaop_p)(void *); | |
1303 | struct vnodeopv_entry_desc cd9660_cdxaop_entries[] = { | |
91447636 A |
1304 | { &vnop_default_desc, (VOPFUNC)vn_default_error }, |
1305 | { &vnop_lookup_desc, (VOPFUNC)cd9660_lookup }, /* lookup */ | |
1306 | { &vnop_create_desc, (VOPFUNC)cd9660_create }, /* create */ | |
1307 | { &vnop_mknod_desc, (VOPFUNC)cd9660_mknod }, /* mknod */ | |
1308 | { &vnop_open_desc, (VOPFUNC)cd9660_open }, /* open */ | |
1309 | { &vnop_close_desc, (VOPFUNC)cd9660_close }, /* close */ | |
1310 | { &vnop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */ | |
1311 | { &vnop_read_desc, (VOPFUNC)cd9660_xa_read }, /* read */ | |
1312 | { &vnop_write_desc, (VOPFUNC)cd9660_write }, /* write */ | |
1313 | { &vnop_ioctl_desc, (VOPFUNC)cd9660_ioctl }, /* ioctl */ | |
1314 | { &vnop_select_desc, (VOPFUNC)cd9660_select }, /* select */ | |
1315 | { &vnop_mmap_desc, (VOPFUNC)cd9660_mmap }, /* mmap */ | |
1316 | { &vnop_fsync_desc, (VOPFUNC)cd9660_fsync }, /* fsync */ | |
1317 | { &vnop_remove_desc, (VOPFUNC)cd9660_remove }, /* remove */ | |
1318 | { &vnop_link_desc, (VOPFUNC)cd9660_link }, /* link */ | |
1319 | { &vnop_rename_desc, (VOPFUNC)cd9660_rename }, /* rename */ | |
1320 | { &vnop_copyfile_desc, (VOPFUNC)cd9660_copyfile },/* copyfile */ | |
1321 | { &vnop_mkdir_desc, (VOPFUNC)cd9660_mkdir }, /* mkdir */ | |
1322 | { &vnop_rmdir_desc, (VOPFUNC)cd9660_rmdir }, /* rmdir */ | |
1323 | { &vnop_symlink_desc, (VOPFUNC)cd9660_symlink }, /* symlink */ | |
1324 | { &vnop_readdir_desc, (VOPFUNC)cd9660_readdir }, /* readdir */ | |
1325 | { &vnop_readlink_desc, (VOPFUNC)cd9660_readlink },/* readlink */ | |
1326 | { &vnop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */ | |
1327 | { &vnop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */ | |
1328 | { &vnop_strategy_desc, (VOPFUNC)cd9660_strategy },/* strategy */ | |
1329 | { &vnop_pathconf_desc, (VOPFUNC)cd9660_pathconf },/* pathconf */ | |
1330 | { &vnop_advlock_desc, (VOPFUNC)cd9660_advlock }, /* advlock */ | |
1331 | { &vnop_bwrite_desc, (VOPFUNC)vn_bwrite }, | |
1332 | { &vnop_pagein_desc, (VOPFUNC)cd9660_xa_pagein }, /* Pagein */ | |
1333 | { &vnop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */ | |
1334 | { &vnop_getattrlist_desc, (VOPFUNC)cd9660_getattrlist }, /* getattrlist */ | |
55e303ae A |
1335 | { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL } |
1336 | }; | |
1337 | struct vnodeopv_desc cd9660_cdxaop_opv_desc = | |
1338 | { &cd9660_cdxaop_p, cd9660_cdxaop_entries }; | |
1339 | ||
1c79356b A |
1340 | /* |
1341 | * Special device vnode ops | |
1342 | */ | |
1343 | int (**cd9660_specop_p)(void *); | |
1344 | struct vnodeopv_entry_desc cd9660_specop_entries[] = { | |
91447636 A |
1345 | { &vnop_default_desc, (VOPFUNC)vn_default_error }, |
1346 | { &vnop_lookup_desc, (VOPFUNC)spec_lookup }, /* lookup */ | |
1347 | { &vnop_create_desc, (VOPFUNC)spec_create }, /* create */ | |
1348 | { &vnop_mknod_desc, (VOPFUNC)spec_mknod }, /* mknod */ | |
1349 | { &vnop_open_desc, (VOPFUNC)spec_open }, /* open */ | |
1350 | { &vnop_close_desc, (VOPFUNC)spec_close }, /* close */ | |
1351 | { &vnop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */ | |
1352 | { &vnop_read_desc, (VOPFUNC)spec_read }, /* read */ | |
1353 | { &vnop_write_desc, (VOPFUNC)spec_write }, /* write */ | |
1354 | { &vnop_ioctl_desc, (VOPFUNC)spec_ioctl }, /* ioctl */ | |
1355 | { &vnop_select_desc, (VOPFUNC)spec_select }, /* select */ | |
1356 | { &vnop_mmap_desc, (VOPFUNC)spec_mmap }, /* mmap */ | |
1357 | { &vnop_fsync_desc, (VOPFUNC)spec_fsync }, /* fsync */ | |
1358 | { &vnop_remove_desc, (VOPFUNC)spec_remove }, /* remove */ | |
1359 | { &vnop_link_desc, (VOPFUNC)spec_link }, /* link */ | |
1360 | { &vnop_rename_desc, (VOPFUNC)spec_rename }, /* rename */ | |
1361 | { &vnop_mkdir_desc, (VOPFUNC)spec_mkdir }, /* mkdir */ | |
1362 | { &vnop_rmdir_desc, (VOPFUNC)spec_rmdir }, /* rmdir */ | |
1363 | { &vnop_symlink_desc, (VOPFUNC)spec_symlink }, /* symlink */ | |
1364 | { &vnop_readdir_desc, (VOPFUNC)spec_readdir }, /* readdir */ | |
1365 | { &vnop_readlink_desc, (VOPFUNC)spec_readlink }, /* readlink */ | |
1366 | { &vnop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */ | |
1367 | { &vnop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */ | |
1368 | { &vnop_strategy_desc, (VOPFUNC)spec_strategy }, /* strategy */ | |
1369 | { &vnop_pathconf_desc, (VOPFUNC)spec_pathconf }, /* pathconf */ | |
1370 | { &vnop_advlock_desc, (VOPFUNC)spec_advlock }, /* advlock */ | |
1371 | { &vnop_bwrite_desc, (VOPFUNC)vn_bwrite }, | |
8ad349bb | 1372 | { &vnop_devblocksize_desc, (VOPFUNC)spec_devblocksize }, /* devblocksize */ |
91447636 A |
1373 | { &vnop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */ |
1374 | { &vnop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */ | |
1375 | { &vnop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */ | |
1376 | { &vnop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */ | |
1377 | { &vnop_blockmap_desc, (VOPFUNC)cd9660_blockmap }, /* blockmap */ | |
1c79356b A |
1378 | { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL } |
1379 | }; | |
1380 | struct vnodeopv_desc cd9660_specop_opv_desc = | |
1381 | { &cd9660_specop_p, cd9660_specop_entries }; | |
1382 | ||
1383 | #if FIFO | |
1384 | int (**cd9660_fifoop_p)(void *); | |
1385 | struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { | |
91447636 A |
1386 | { &vnop_default_desc, (VOPFUNC)vn_default_error }, |
1387 | { &vnop_lookup_desc, (VOPFUNC)fifo_lookup }, /* lookup */ | |
1388 | { &vnop_create_desc, (VOPFUNC)fifo_create }, /* create */ | |
1389 | { &vnop_mknod_desc, (VOPFUNC)fifo_mknod }, /* mknod */ | |
1390 | { &vnop_open_desc, (VOPFUNC)fifo_open }, /* open */ | |
1391 | { &vnop_close_desc, (VOPFUNC)fifo_close }, /* close */ | |
1392 | { &vnop_getattr_desc, (VOPFUNC)cd9660_getattr }, /* getattr */ | |
1393 | { &vnop_read_desc, (VOPFUNC)fifo_read }, /* read */ | |
1394 | { &vnop_write_desc, (VOPFUNC)fifo_write }, /* write */ | |
1395 | { &vnop_ioctl_desc, (VOPFUNC)fifo_ioctl }, /* ioctl */ | |
1396 | { &vnop_select_desc, (VOPFUNC)fifo_select }, /* select */ | |
1397 | { &vnop_mmap_desc, (VOPFUNC)fifo_mmap }, /* mmap */ | |
1398 | { &vnop_fsync_desc, (VOPFUNC)fifo_fsync }, /* fsync */ | |
1399 | { &vnop_remove_desc, (VOPFUNC)fifo_remove }, /* remove */ | |
1400 | { &vnop_link_desc, (VOPFUNC)fifo_link } , /* link */ | |
1401 | { &vnop_rename_desc, (VOPFUNC)fifo_rename }, /* rename */ | |
1402 | { &vnop_mkdir_desc, (VOPFUNC)fifo_mkdir }, /* mkdir */ | |
1403 | { &vnop_rmdir_desc, (VOPFUNC)fifo_rmdir }, /* rmdir */ | |
1404 | { &vnop_symlink_desc, (VOPFUNC)fifo_symlink }, /* symlink */ | |
1405 | { &vnop_readdir_desc, (VOPFUNC)fifo_readdir }, /* readdir */ | |
1406 | { &vnop_readlink_desc, (VOPFUNC)fifo_readlink }, /* readlink */ | |
1407 | { &vnop_inactive_desc, (VOPFUNC)cd9660_inactive },/* inactive */ | |
1408 | { &vnop_reclaim_desc, (VOPFUNC)cd9660_reclaim }, /* reclaim */ | |
1409 | { &vnop_strategy_desc, (VOPFUNC)fifo_strategy }, /* strategy */ | |
1410 | { &vnop_pathconf_desc, (VOPFUNC)fifo_pathconf }, /* pathconf */ | |
1411 | { &vnop_advlock_desc, (VOPFUNC)fifo_advlock }, /* advlock */ | |
1412 | { &vnop_bwrite_desc, (VOPFUNC)vn_bwrite }, | |
1413 | { &vnop_pagein_desc, (VOPFUNC)cd9660_pagein }, /* Pagein */ | |
1414 | { &vnop_pageout_desc, (VOPFUNC)cd9660_pageout }, /* Pageout */ | |
1415 | { &vnop_blktooff_desc, (VOPFUNC)cd9660_blktooff }, /* blktooff */ | |
1416 | { &vnop_offtoblk_desc, (VOPFUNC)cd9660_offtoblk }, /* offtoblk */ | |
1c79356b A |
1417 | { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL } |
1418 | }; | |
1419 | struct vnodeopv_desc cd9660_fifoop_opv_desc = | |
1420 | { &cd9660_fifoop_p, cd9660_fifoop_entries }; | |
1421 | #endif /* FIFO */ |