]>
git.saurik.com Git - apple/xnu.git/blob - bsd/isofs/cd9660/cd9660_node.c
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* $NetBSD: cd9660_node.c,v 1.13 1994/12/24 15:30:07 cgd Exp $ */
31 * Copyright (c) 1982, 1986, 1989, 1994
32 * The Regents of the University of California. All rights reserved.
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).
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
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.
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
67 * @(#)cd9660_node.c 8.5 (Berkeley) 12/5/94
72 * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc
73 * 17-Feb-98 radar 1669467 - changed lock protocols to use the lock manager - chw
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/mount.h>
83 #include <sys/vnode.h>
84 #include <sys/kernel.h>
85 #include <sys/malloc.h>
88 #include <sys/namei.h>
90 #include <isofs/cd9660/iso.h>
91 #include <isofs/cd9660/cd9660_node.h>
92 #include <isofs/cd9660/iso_rrip.h>
93 #include <isofs/cd9660/cd9660_mount.h>
96 * Structures associated with iso_node caching.
98 struct iso_node
**isohashtbl
;
100 #define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
103 struct iso_node
**idvhashtbl
;
105 #define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
108 /* defined in bsd/vfs/vfs_subr.c */
109 extern int prtactive
; /* 1 => print out reclaim of active vnodes */
111 extern u_char isonullname
[];
113 * Initialize hash links for inodes and dnodes.
116 cd9660_init(__unused
struct vfsconf
*cp
)
122 cd9660_hashinit(void)
125 isohashtbl
= hashinit(desiredvnodes
, M_ISOFSMNT
, &isohash
);
128 idvhashtbl
= hashinit(desiredvnodes
/ 8, M_ISOFSMNT
, &idvhash
);
135 * Enter a new node into the device hash list
138 iso_dmap(dev_t device
, ino_t inum
, int create
)
140 register struct iso_dnode
**dpp
, *dp
, *dq
;
142 dpp
= &idvhashtbl
[DNOHASH(device
, inum
)];
143 for (dp
= *dpp
;; dp
= dp
->d_next
) {
146 if (inum
== dp
->i_number
&& device
== dp
->i_dev
)
152 MALLOC(dp
, struct iso_dnode
*, sizeof(struct iso_dnode
), M_CACHE
,
158 dq
->d_prev
= dp
->d_next
;
167 iso_dunmap(dev_t device
)
169 struct iso_dnode
**dpp
, *dp
, *dq
;
171 for (dpp
= idvhashtbl
; dpp
<= idvhashtbl
+ idvhash
; dpp
++) {
172 for (dp
= *dpp
; dp
!= NULL
; dp
= dq
)
174 if (device
== dp
->i_dev
) {
176 dq
->d_prev
= dp
->d_prev
;
186 * Use the device/inum pair to find the incore inode, and return a pointer
187 * to it. If it is in core, but locked, wait for it.
190 cd9660_ihashget(dev_t device
, ino_t inum
, __unused
struct proc
*p
)
192 register struct iso_node
*ip
;
197 for (ip
= isohashtbl
[INOHASH(device
, inum
)]; ip
; ip
= ip
->i_next
) {
198 if (inum
== ip
->i_number
&& device
== ip
->i_dev
) {
200 if (ISSET(ip
->i_flag
, ISO_INALLOC
)) {
202 * inode is being created... wait for it
203 * to be ready for consumption
205 SET(ip
->i_flag
, ISO_INWALLOC
);
206 tsleep((caddr_t
)ip
, PINOD
, "cd9960_ihashget", 0);
211 * the vid needs to be grabbed before we drop
212 * lock protecting the hash
217 * we currently depend on running under the FS funnel
218 * when we do proper locking and advertise ourselves
219 * as thread safe, we'll need a lock to protect the
220 * hash lookup... this is where we would drop it
222 if (vnode_getwithvid(vp
, vid
)) {
224 * If vnode is being reclaimed, or has
225 * already changed identity, no need to wait
236 * Insert the inode into the hash table, and return it locked.
239 cd9660_ihashins(struct iso_node
*ip
)
241 struct iso_node
**ipp
, *iq
;
243 /* lock the inode, then put it on the appropriate hash list */
245 ipp
= &isohashtbl
[INOHASH(ip
->i_dev
, ip
->i_number
)];
247 iq
->i_prev
= &ip
->i_next
;
254 * Remove the inode from the hash table.
257 cd9660_ihashrem(register struct iso_node
*ip
)
259 register struct iso_node
*iq
;
261 if ((iq
= ip
->i_next
))
262 iq
->i_prev
= ip
->i_prev
;
264 #if 1 /* was ifdef DIAGNOSTIC */
271 * Last reference to an inode... if we're done with
272 * it, go ahead and recycle it for other use
275 cd9660_inactive(struct vnop_inactive_args
*ap
)
277 vnode_t vp
= ap
->a_vp
;
278 struct iso_node
*ip
= VTOI(vp
);
281 * If we are done with the inode, reclaim it
282 * so that it can be reused immediately.
284 if (ip
->inode
.iso_mode
== 0)
291 * Reclaim an inode so that it can be used for other purposes.
294 cd9660_reclaim(struct vnop_reclaim_args
*ap
)
296 vnode_t vp
= ap
->a_vp
;
297 struct iso_node
*ip
= VTOI(vp
);
299 vnode_removefsref(vp
);
301 * Remove the inode from its hash chain.
306 vnode_t devvp
= ip
->i_devvp
;
310 vnode_clearfsnode(vp
);
312 if (ip
->i_namep
!= isonullname
)
313 FREE(ip
->i_namep
, M_TEMP
);
314 if (ip
->i_riff
!= NULL
)
315 FREE(ip
->i_riff
, M_TEMP
);
316 FREE_ZONE(ip
, sizeof(struct iso_node
), M_ISOFSNODE
);
325 cd9660_defattr(struct iso_directory_record
*isodir
, struct iso_node
*inop
,
328 struct buf
*bp2
= NULL
;
330 struct iso_extended_attributes
*ap
= NULL
;
333 if ( isonum_711(isodir
->flags
) & directoryBit
) {
334 inop
->inode
.iso_mode
= S_IFDIR
;
336 * If we return 2, fts() will assume there are no subdirectories
337 * (just links for the path and .), so instead we return 1.
339 inop
->inode
.iso_links
= 1;
341 inop
->inode
.iso_mode
= S_IFREG
;
342 inop
->inode
.iso_links
= 1;
345 && ((imp
= inop
->i_mnt
)->im_flags
& ISOFSMNT_EXTATT
)
346 && (off
= isonum_711(isodir
->ext_attr_length
))) {
347 cd9660_blkatoff(ITOV(inop
), (off_t
)-(off
<< imp
->im_bshift
), NULL
, &bp2
);
351 ap
= (struct iso_extended_attributes
*)((char *)0 + buf_dataptr(bp
));
353 if (isonum_711(ap
->version
) == 1) {
354 if (!(ap
->perm
[0]&0x40))
355 inop
->inode
.iso_mode
|= VEXEC
>> 6;
356 if (!(ap
->perm
[0]&0x10))
357 inop
->inode
.iso_mode
|= VREAD
>> 6;
358 if (!(ap
->perm
[0]&4))
359 inop
->inode
.iso_mode
|= VEXEC
>> 3;
360 if (!(ap
->perm
[0]&1))
361 inop
->inode
.iso_mode
|= VREAD
>> 3;
362 if (!(ap
->perm
[1]&0x40))
363 inop
->inode
.iso_mode
|= VEXEC
;
364 if (!(ap
->perm
[1]&0x10))
365 inop
->inode
.iso_mode
|= VREAD
;
366 inop
->inode
.iso_uid
= isonum_723(ap
->owner
); /* what about 0? */
367 inop
->inode
.iso_gid
= isonum_723(ap
->group
); /* what about 0? */
372 inop
->inode
.iso_mode
|= VREAD
|VWRITE
|VEXEC
|(VREAD
|VEXEC
)>>3|(VREAD
|VEXEC
)>>6;
373 inop
->inode
.iso_uid
= ISO_UNKNOWNUID
;
374 inop
->inode
.iso_gid
= ISO_UNKNOWNGID
;
384 cd9660_deftstamp(struct iso_directory_record
*isodir
, struct iso_node
*inop
,
387 struct buf
*bp2
= NULL
;
389 struct iso_extended_attributes
*ap
= NULL
;
393 && ((imp
= inop
->i_mnt
)->im_flags
& ISOFSMNT_EXTATT
)
394 && (off
= isonum_711(isodir
->ext_attr_length
)))
396 cd9660_blkatoff(ITOV(inop
), (off_t
)-(off
<< imp
->im_bshift
), NULL
, &bp2
);
400 ap
= (struct iso_extended_attributes
*)((char *)0 + buf_dataptr(bp
));
402 if (isonum_711(ap
->version
) == 1) {
403 if (!cd9660_tstamp_conv17(ap
->ftime
,&inop
->inode
.iso_atime
))
404 cd9660_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_atime
);
405 if (!cd9660_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_ctime
))
406 inop
->inode
.iso_ctime
= inop
->inode
.iso_atime
;
407 if (!cd9660_tstamp_conv17(ap
->mtime
,&inop
->inode
.iso_mtime
))
408 inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
413 cd9660_tstamp_conv7(isodir
->date
,&inop
->inode
.iso_ctime
);
414 inop
->inode
.iso_atime
= inop
->inode
.iso_ctime
;
415 inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
422 cd9660_tstamp_conv7(u_char
*pi
, struct timespec
*pu
)
425 int y
, m
, d
, hour
, minute
, second
, mytz
;
441 /* computes day number relative to Sept. 19th,1989 */
442 /* don't even *THINK* about changing formula. It works! */
443 days
= 367*(y
-1980)-7*(y
+(m
+9)/12)/4-3*((y
+(m
-9)/7)/100+1)/4+275*m
/9+d
-100;
446 * Changed :-) to make it relative to Jan. 1st, 1970
447 * and to disambiguate negative division
449 days
= 367*(y
-1960)-7*(y
+(m
+9)/12)/4-3*((y
+(m
+9)/12-1)/100+1)/4+275*m
/9+d
-239;
451 crtime
= ((((days
* 24) + hour
) * 60 + minute
) * 60) + second
;
453 /* timezone offset is unreliable on some disks */
454 if (-48 <= mytz
&& mytz
<= 52)
455 crtime
-= mytz
* 15 * 60;
463 cd9660_chars2ui(u_char
*begin
, int len
)
467 for (rc
= 0; --len
>= 0;) {
469 rc
+= *begin
++ - '0';
475 cd9660_tstamp_conv17(u_char
*pi
, struct timespec
*pu
)
479 /* year:"0001"-"9999" -> -1900 */
480 buf
[0] = cd9660_chars2ui(pi
,4) - 1900;
482 /* month: " 1"-"12" -> 1 - 12 */
483 buf
[1] = cd9660_chars2ui(pi
+ 4,2);
485 /* day: " 1"-"31" -> 1 - 31 */
486 buf
[2] = cd9660_chars2ui(pi
+ 6,2);
488 /* hour: " 0"-"23" -> 0 - 23 */
489 buf
[3] = cd9660_chars2ui(pi
+ 8,2);
491 /* minute:" 0"-"59" -> 0 - 59 */
492 buf
[4] = cd9660_chars2ui(pi
+ 10,2);
494 /* second:" 0"-"59" -> 0 - 59 */
495 buf
[5] = cd9660_chars2ui(pi
+ 12,2);
497 /* difference of GMT */
500 return cd9660_tstamp_conv7(buf
,pu
);
504 isodirino(struct iso_directory_record
*isodir
, struct iso_mnt
*imp
)
508 ino
= (isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
))