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