]>
git.saurik.com Git - apple/xnu.git/blob - bsd/isofs/cd9660/cd9660_node.c
b9b0cdcce8c98343d31f1d7a4b0d5c04ba51fb59
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* $NetBSD: cd9660_node.c,v 1.13 1994/12/24 15:30:07 cgd Exp $ */
28 * Copyright (c) 1982, 1986, 1989, 1994
29 * The Regents of the University of California. All rights reserved.
31 * This code is derived from software contributed to Berkeley
32 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
33 * Support code is derived from software contributed to Berkeley
34 * by Atsushi Murai (amurai@spec.co.jp).
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * @(#)cd9660_node.c 8.5 (Berkeley) 12/5/94
69 * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc
70 * 17-Feb-98 radar 1669467 - changed lock protocols to use the lock manager - chw
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/mount.h>
80 #include <sys/vnode.h>
81 #include <sys/kernel.h>
82 #include <sys/malloc.h>
86 #include <isofs/cd9660/iso.h>
87 #include <isofs/cd9660/cd9660_node.h>
88 #include <isofs/cd9660/iso_rrip.h>
89 #include <isofs/cd9660/cd9660_mount.h>
92 * Structures associated with iso_node caching.
94 struct iso_node
**isohashtbl
;
96 #define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
99 struct iso_node
**idvhashtbl
;
101 #define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
104 /* defined in bsd/ufs/ufs/ufs_inode.c */
105 extern int prtactive
; /* 1 => print out reclaim of active vnodes */
107 extern void cache_purge (struct vnode
*vp
);
109 extern u_char isonullname
[];
111 * Initialize hash links for inodes and dnodes.
117 isohashtbl
= hashinit(desiredvnodes
, M_ISOFSMNT
, &isohash
);
119 idvhashtbl
= hashinit(desiredvnodes
/ 8, M_ISOFSMNT
, &idvhash
);
126 * Enter a new node into the device hash list
129 iso_dmap(device
, inum
, create
)
134 register struct iso_dnode
**dpp
, *dp
, *dq
;
136 dpp
= &idvhashtbl
[DNOHASH(device
, inum
)];
137 for (dp
= *dpp
;; dp
= dp
->d_next
) {
140 if (inum
== dp
->i_number
&& device
== dp
->i_dev
)
146 MALLOC(dp
, struct iso_dnode
*, sizeof(struct iso_dnode
), M_CACHE
,
152 dq
->d_prev
= dp
->d_next
;
164 struct iso_dnode
**dpp
, *dp
, *dq
;
166 for (dpp
= idvhashtbl
; dpp
<= idvhashtbl
+ idvhash
; dpp
++) {
167 for (dp
= *dpp
; dp
!= NULL
; dp
= dq
)
169 if (device
== dp
->i_dev
) {
171 dq
->d_prev
= dp
->d_prev
;
181 * Use the device/inum pair to find the incore inode, and return a pointer
182 * to it. If it is in core, but locked, wait for it.
185 cd9660_ihashget(device
, inum
, p
)
190 register struct iso_node
*ip
;
194 for (ip
= isohashtbl
[INOHASH(device
, inum
)];; ip
= ip
->i_next
) {
197 if (inum
== ip
->i_number
&& device
== ip
->i_dev
) {
199 * This is my most dangerous change. I am not waiting for
200 * the inode lock anymore (ufs doesn't, why should we) and
201 * I'm worried because there is not lock on the hashtable,
202 * but there wasn't before so I'll let it go for now.
206 simple_lock(&vp
->v_interlock
);
207 if (!vget(vp
, LK_EXCLUSIVE
| LK_INTERLOCK
| LK_RETRY
, p
))
216 * Insert the inode into the hash table, and return it locked.
222 struct iso_node
**ipp
, *iq
;
223 struct proc
*p
= current_proc();
225 /* lock the inode, then put it on the appropriate hash list */
226 lockmgr(&ip
->i_lock
, LK_EXCLUSIVE
, (struct slock
*)0, p
);
228 ipp
= &isohashtbl
[INOHASH(ip
->i_dev
, ip
->i_number
)];
230 iq
->i_prev
= &ip
->i_next
;
237 * Remove the inode from the hash table.
241 register struct iso_node
*ip
;
243 register struct iso_node
*iq
;
245 if ((iq
= ip
->i_next
))
246 iq
->i_prev
= ip
->i_prev
;
248 #if 1 /* was ifdef DIAGNOSTIC */
255 * Last reference to an inode, write the inode out and if necessary,
256 * truncate and deallocate the file.
260 struct vop_inactive_args
/* {
265 struct vnode
*vp
= ap
->a_vp
;
266 struct proc
*p
= ap
->a_p
;
267 register struct iso_node
*ip
= VTOI(vp
);
270 if (prtactive
&& vp
->v_usecount
!= 0)
271 vprint("cd9660_inactive: pushing active", vp
);
273 * We need to unlock the inode here. If we don't panics or
274 * hangs will ensue. Our callers expect us to take care of this.
280 * If we are done with the inode, reclaim it
281 * so that it can be reused immediately.
283 if (vp
->v_usecount
== 0 && ip
->inode
.iso_mode
== 0)
290 * Reclaim an inode so that it can be used for other purposes.
294 struct vop_reclaim_args
/* {
298 register struct vnode
*vp
= ap
->a_vp
;
299 register struct iso_node
*ip
= VTOI(vp
);
301 if (prtactive
&& vp
->v_usecount
!= 0)
302 vprint("cd9660_reclaim: pushing active", vp
);
304 * Remove the inode from its hash chain.
308 * Purge old data structures associated with the inode.
312 struct vnode
*tvp
= ip
->i_devvp
;
316 if (ip
->i_namep
!= isonullname
)
317 FREE(ip
->i_namep
, M_TEMP
);
318 FREE_ZONE(vp
->v_data
, sizeof(struct iso_node
), M_ISOFSNODE
);
327 cd9660_defattr(isodir
, inop
, bp
)
328 struct iso_directory_record
*isodir
;
329 struct iso_node
*inop
;
332 struct buf
*bp2
= NULL
;
334 struct iso_extended_attributes
*ap
= NULL
;
337 if ( isonum_711(isodir
->flags
) & directoryBit
) {
338 inop
->inode
.iso_mode
= S_IFDIR
;
340 * If we return 2, fts() will assume there are no subdirectories
341 * (just links for the path and .), so instead we return 1.
343 inop
->inode
.iso_links
= 1;
345 inop
->inode
.iso_mode
= S_IFREG
;
346 inop
->inode
.iso_links
= 1;
349 && ((imp
= inop
->i_mnt
)->im_flags
& ISOFSMNT_EXTATT
)
350 && (off
= isonum_711(isodir
->ext_attr_length
))) {
351 VOP_BLKATOFF(ITOV(inop
), (off_t
)-(off
<< imp
->im_bshift
), NULL
,
356 ap
= (struct iso_extended_attributes
*)bp
->b_data
;
358 if (isonum_711(ap
->version
) == 1) {
359 if (!(ap
->perm
[0]&0x40))
360 inop
->inode
.iso_mode
|= VEXEC
>> 6;
361 if (!(ap
->perm
[0]&0x10))
362 inop
->inode
.iso_mode
|= VREAD
>> 6;
363 if (!(ap
->perm
[0]&4))
364 inop
->inode
.iso_mode
|= VEXEC
>> 3;
365 if (!(ap
->perm
[0]&1))
366 inop
->inode
.iso_mode
|= VREAD
>> 3;
367 if (!(ap
->perm
[1]&0x40))
368 inop
->inode
.iso_mode
|= VEXEC
;
369 if (!(ap
->perm
[1]&0x10))
370 inop
->inode
.iso_mode
|= VREAD
;
371 inop
->inode
.iso_uid
= isonum_723(ap
->owner
); /* what about 0? */
372 inop
->inode
.iso_gid
= isonum_723(ap
->group
); /* what about 0? */
377 inop
->inode
.iso_mode
|= VREAD
|VEXEC
|(VREAD
|VEXEC
)>>3|(VREAD
|VEXEC
)>>6;
378 inop
->inode
.iso_uid
= (uid_t
)0;
379 inop
->inode
.iso_gid
= (gid_t
)0;
389 cd9660_deftstamp(isodir
,inop
,bp
)
390 struct iso_directory_record
*isodir
;
391 struct iso_node
*inop
;
394 struct buf
*bp2
= NULL
;
396 struct iso_extended_attributes
*ap
= NULL
;
400 && ((imp
= inop
->i_mnt
)->im_flags
& ISOFSMNT_EXTATT
)
401 && (off
= isonum_711(isodir
->ext_attr_length
)))
403 VOP_BLKATOFF(ITOV(inop
), (off_t
)-(off
<< imp
->im_bshift
), NULL
, &bp2
);
407 ap
= (struct iso_extended_attributes
*)bp
->b_data
;
409 if (isonum_711(ap
->version
) == 1) {
410 if (!cd9660_tstamp_conv17(ap
->ftime
,&inop
->inode
.iso_atime
))
411 cd9660_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_atime
);
412 if (!cd9660_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_ctime
))
413 inop
->inode
.iso_ctime
= inop
->inode
.iso_atime
;
414 if (!cd9660_tstamp_conv17(ap
->mtime
,&inop
->inode
.iso_mtime
))
415 inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
420 cd9660_tstamp_conv7(isodir
->date
,&inop
->inode
.iso_ctime
);
421 inop
->inode
.iso_atime
= inop
->inode
.iso_ctime
;
422 inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
429 cd9660_tstamp_conv7(pi
,pu
)
434 int y
, m
, d
, hour
, minute
, second
, tz
;
450 /* computes day number relative to Sept. 19th,1989 */
451 /* don't even *THINK* about changing formula. It works! */
452 days
= 367*(y
-1980)-7*(y
+(m
+9)/12)/4-3*((y
+(m
-9)/7)/100+1)/4+275*m
/9+d
-100;
455 * Changed :-) to make it relative to Jan. 1st, 1970
456 * and to disambiguate negative division
458 days
= 367*(y
-1960)-7*(y
+(m
+9)/12)/4-3*((y
+(m
+9)/12-1)/100+1)/4+275*m
/9+d
-239;
460 crtime
= ((((days
* 24) + hour
) * 60 + minute
) * 60) + second
;
462 /* timezone offset is unreliable on some disks */
463 if (-48 <= tz
&& tz
<= 52)
464 crtime
-= tz
* 15 * 60;
472 cd9660_chars2ui(begin
,len
)
478 for (rc
= 0; --len
>= 0;) {
480 rc
+= *begin
++ - '0';
486 cd9660_tstamp_conv17(pi
,pu
)
492 /* year:"0001"-"9999" -> -1900 */
493 buf
[0] = cd9660_chars2ui(pi
,4) - 1900;
495 /* month: " 1"-"12" -> 1 - 12 */
496 buf
[1] = cd9660_chars2ui(pi
+ 4,2);
498 /* day: " 1"-"31" -> 1 - 31 */
499 buf
[2] = cd9660_chars2ui(pi
+ 6,2);
501 /* hour: " 0"-"23" -> 0 - 23 */
502 buf
[3] = cd9660_chars2ui(pi
+ 8,2);
504 /* minute:" 0"-"59" -> 0 - 59 */
505 buf
[4] = cd9660_chars2ui(pi
+ 10,2);
507 /* second:" 0"-"59" -> 0 - 59 */
508 buf
[5] = cd9660_chars2ui(pi
+ 12,2);
510 /* difference of GMT */
513 return cd9660_tstamp_conv7(buf
,pu
);
517 isodirino(isodir
, imp
)
518 struct iso_directory_record
*isodir
;
523 ino
= (isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
))