* Copyright (c) 1982, 1986, 1989, 1994, 1995
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
* %sccs.include.redist.c%
* @(#)cd9660_node.c 8.7 (Berkeley) %G%
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/cd9660_mount.h>
#include <isofs/cd9660/iso_rrip.h>
* Structures associated with iso_node caching.
struct iso_node
**isohashtbl
;
#define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
struct simplelock cd9660_ihash_slock
;
struct iso_node
**idvhashtbl
;
#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
int prtactive
; /* 1 => print out reclaim of active vnodes */
* Initialize hash links for inodes and dnodes.
isohashtbl
= hashinit(desiredvnodes
, M_ISOFSMNT
, &isohash
);
simple_lock_init(&cd9660_ihash_slock
);
idvhashtbl
= hashinit(desiredvnodes
/ 8, M_ISOFSMNT
, &idvhash
);
* Enter a new node into the device hash list
iso_dmap(device
, inum
, create
)
register struct iso_dnode
**dpp
, *dp
, *dq
;
dpp
= &idvhashtbl
[DNOHASH(device
, inum
)];
for (dp
= *dpp
;; dp
= dp
->d_next
) {
if (inum
== dp
->i_number
&& device
== dp
->i_dev
)
MALLOC(dp
, struct iso_dnode
*, sizeof(struct iso_dnode
), M_CACHE
,
struct iso_dnode
**dpp
, *dp
, *dq
;
for (dpp
= idvhashtbl
; dpp
<= idvhashtbl
+ idvhash
; dpp
++) {
for (dp
= *dpp
; dp
!= NULL
; dp
= dq
)
if (device
== dp
->i_dev
) {
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, but locked, wait for it.
cd9660_ihashget(dev
, inum
)
struct proc
*p
= curproc
; /* XXX */
simple_lock(&cd9660_ihash_slock
);
for (ip
= isohashtbl
[INOHASH(dev
, inum
)]; ip
; ip
= ip
->i_next
) {
if (inum
== ip
->i_number
&& dev
== ip
->i_dev
) {
simple_lock(&vp
->v_interlock
);
simple_unlock(&cd9660_ihash_slock
);
if (vget(vp
, LK_EXCLUSIVE
| LK_INTERLOCK
, p
))
simple_unlock(&cd9660_ihash_slock
);
* Insert the inode into the hash table, and return it locked.
struct proc
*p
= curproc
; /* XXX */
struct iso_node
**ipp
, *iq
;
simple_lock(&cd9660_ihash_slock
);
ipp
= &isohashtbl
[INOHASH(ip
->i_dev
, ip
->i_number
)];
iq
->i_prev
= &ip
->i_next
;
simple_unlock(&cd9660_ihash_slock
);
lockmgr(&ip
->i_lock
, LK_EXCLUSIVE
, (struct simplelock
*)0, p
);
* Remove the inode from the hash table.
register struct iso_node
*ip
;
register struct iso_node
*iq
;
simple_lock(&cd9660_ihash_slock
);
simple_unlock(&cd9660_ihash_slock
);
* Last reference to an inode, write the inode out and if necessary,
* truncate and deallocate the file.
struct vop_inactive_args
/* {
struct vnode
*vp
= ap
->a_vp
;
register struct iso_node
*ip
= VTOI(vp
);
if (prtactive
&& vp
->v_usecount
!= 0)
vprint("cd9660_inactive: pushing active", vp
);
* If we are done with the inode, reclaim it
* so that it can be reused immediately.
if (vp
->v_usecount
== 0 && ip
->inode
.iso_mode
== 0)
* Reclaim an inode so that it can be used for other purposes.
struct vop_reclaim_args
/* {
register struct vnode
*vp
= ap
->a_vp
;
register struct iso_node
*ip
= VTOI(vp
);
if (prtactive
&& vp
->v_usecount
!= 0)
vprint("cd9660_reclaim: pushing active", vp
);
* Remove the inode from its hash chain.
* Purge old data structures associated with the inode.
FREE(vp
->v_data
, M_ISOFSNODE
);
cd9660_defattr(isodir
, inop
, bp
)
struct iso_directory_record
*isodir
;
struct iso_extended_attributes
*ap
= NULL
;
if (isonum_711(isodir
->flags
)&2) {
inop
->inode
.iso_mode
= S_IFDIR
;
* If we return 2, fts() will assume there are no subdirectories
* (just links for the path and .), so instead we return 1.
inop
->inode
.iso_links
= 1;
inop
->inode
.iso_mode
= S_IFREG
;
inop
->inode
.iso_links
= 1;
&& ((imp
= inop
->i_mnt
)->im_flags
& ISOFSMNT_EXTATT
)
&& (off
= isonum_711(isodir
->ext_attr_length
))) {
VOP_BLKATOFF(ITOV(inop
), (off_t
)-(off
<< imp
->im_bshift
), NULL
,
ap
= (struct iso_extended_attributes
*)bp
->b_data
;
if (isonum_711(ap
->version
) == 1) {
inop
->inode
.iso_mode
|= VEXEC
>> 6;
inop
->inode
.iso_mode
|= VREAD
>> 6;
inop
->inode
.iso_mode
|= VEXEC
>> 3;
inop
->inode
.iso_mode
|= VREAD
>> 3;
inop
->inode
.iso_mode
|= VEXEC
;
inop
->inode
.iso_mode
|= VREAD
;
inop
->inode
.iso_uid
= isonum_723(ap
->owner
); /* what about 0? */
inop
->inode
.iso_gid
= isonum_723(ap
->group
); /* what about 0? */
inop
->inode
.iso_mode
|= VREAD
|VEXEC
|(VREAD
|VEXEC
)>>3|(VREAD
|VEXEC
)>>6;
inop
->inode
.iso_uid
= (uid_t
)0;
inop
->inode
.iso_gid
= (gid_t
)0;
cd9660_deftstamp(isodir
,inop
,bp
)
struct iso_directory_record
*isodir
;
struct iso_extended_attributes
*ap
= NULL
;
&& ((imp
= inop
->i_mnt
)->im_flags
& ISOFSMNT_EXTATT
)
&& (off
= isonum_711(isodir
->ext_attr_length
))) {
VOP_BLKATOFF(ITOV(inop
), (off_t
)-(off
<< imp
->im_bshift
), NULL
,
ap
= (struct iso_extended_attributes
*)bp
->b_data
;
if (isonum_711(ap
->version
) == 1) {
if (!cd9660_tstamp_conv17(ap
->ftime
,&inop
->inode
.iso_atime
))
cd9660_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_atime
);
if (!cd9660_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_ctime
))
inop
->inode
.iso_ctime
= inop
->inode
.iso_atime
;
if (!cd9660_tstamp_conv17(ap
->mtime
,&inop
->inode
.iso_mtime
))
inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
cd9660_tstamp_conv7(isodir
->date
,&inop
->inode
.iso_ctime
);
inop
->inode
.iso_atime
= inop
->inode
.iso_ctime
;
inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
cd9660_tstamp_conv7(pi
,pu
)
int y
, m
, d
, hour
, minute
, second
, tz
;
/* computes day number relative to Sept. 19th,1989 */
/* don't even *THINK* about changing formula. It works! */
days
= 367*(y
-1980)-7*(y
+(m
+9)/12)/4-3*((y
+(m
-9)/7)/100+1)/4+275*m
/9+d
-100;
* Changed :-) to make it relative to Jan. 1st, 1970
* and to disambiguate negative division
days
= 367*(y
-1960)-7*(y
+(m
+9)/12)/4-3*((y
+(m
+9)/12-1)/100+1)/4+275*m
/9+d
-239;
crtime
= ((((days
* 24) + hour
) * 60 + minute
) * 60) + second
;
/* timezone offset is unreliable on some disks */
if (-48 <= tz
&& tz
<= 52)
cd9660_chars2ui(begin
,len
)
for (rc
= 0; --len
>= 0;) {
cd9660_tstamp_conv17(pi
,pu
)
/* year:"0001"-"9999" -> -1900 */
buf
[0] = cd9660_chars2ui(pi
,4) - 1900;
/* month: " 1"-"12" -> 1 - 12 */
buf
[1] = cd9660_chars2ui(pi
+ 4,2);
/* day: " 1"-"31" -> 1 - 31 */
buf
[2] = cd9660_chars2ui(pi
+ 6,2);
/* hour: " 0"-"23" -> 0 - 23 */
buf
[3] = cd9660_chars2ui(pi
+ 8,2);
/* minute:" 0"-"59" -> 0 - 59 */
buf
[4] = cd9660_chars2ui(pi
+ 10,2);
/* second:" 0"-"59" -> 0 - 59 */
buf
[5] = cd9660_chars2ui(pi
+ 12,2);
return cd9660_tstamp_conv7(buf
,pu
);
struct iso_directory_record
*isodir
;
ino
= (isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
))