66d81198bf5d5e42b9881c540a5e861d5914d5e8
* Copyright (c) 1982, 1986, 1989, 1994
* 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.1 (Berkeley) %G%
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/isofs_node.h>
#include <isofs/cd9660/iso_rrip.h>
#if ((INOHSZ&(INOHSZ-1)) == 0)
#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1))
#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ)
union iso_ihead
*ih_head
[2];
struct iso_node
*ih_chain
[2];
#if ((DNOHSZ&(DNOHSZ-1)) == 0)
#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1))
#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ)
union iso_dhead
*dh_head
[2];
struct iso_dnode
*dh_chain
[2];
int prtactive
; /* 1 => print out reclaim of active vnodes */
* Initialize hash links for inodes and dnodes.
register union iso_ihead
*ih
= iso_ihead
;
register union iso_dhead
*dh
= iso_dhead
;
for (i
= INOHSZ
; --i
>= 0; ih
++) {
for (i
= DNOHSZ
; --i
>= 0; dh
++) {
* Enter a new node into the device hash list
dh
= &iso_dhead
[DNOHASH(dev
, ino
)];
for (dp
= dh
->dh_chain
[0];
dp
!= (struct iso_dnode
*)dh
;
if (ino
== dp
->i_number
&& dev
== dp
->i_dev
)
return (struct iso_dnode
*)0;
MALLOC(dp
,struct iso_dnode
*,sizeof(struct iso_dnode
),M_CACHE
,M_WAITOK
);
struct iso_dnode
*dp
, *dq
;
for (dh
= iso_dhead
; dh
< iso_dhead
+ DNOHSZ
; dh
++) {
for (dp
= dh
->dh_chain
[0];
dp
!= (struct iso_dnode
*)dh
;
* Look up a ISOFS dinode number to find its incore vnode.
* If it is not in core, read it in from the specified device.
* If it is in core, wait for the lock bit to clear, then
* return the inode locked. Detection and handling of mount
* points must be done by the calling routine.
iso_iget(xp
, ino
, relocated
, ipp
, isodir
)
struct iso_directory_record
*isodir
;
struct mount
*mntp
= ITOV(xp
)->v_mount
;
register struct iso_node
*ip
, *iq
;
register struct vnode
*vp
;
register struct iso_dnode
*dp
;
struct buf
*bp
= NULL
, *bp2
= NULL
;
ih
= &iso_ihead
[INOHASH(dev
, ino
)];
for (ip
= ih
->ih_chain
[0];
ip
!= (struct iso_node
*)ih
;
if (ino
!= ip
->i_number
|| dev
!= ip
->i_dev
)
if ((ip
->i_flag
&ILOCKED
) != 0) {
sleep((caddr_t
)ip
, PINOD
);
* Allocate a new vnode/iso_node.
if (error
= getnewvnode(VT_ISOFS
, mntp
, isofs_vnodeop_p
, &nvp
)) {
MALLOC(ip
, struct iso_node
*, sizeof(struct iso_node
),
bzero((caddr_t
)ip
, sizeof(struct iso_node
));
* Put it onto its hash chain and lock it so that other requests for
* this inode will block if they arrive while we are sleeping waiting
* for old data structures to be purged or for the contents of the
* disk portion of this inode to be read.
ip
->i_devvp
= imp
->im_devvp
;
* On relocated directories we must
* read the `.' entry out of a dir.
ip
->iso_start
= ino
>> imp
->im_bshift
;
if (error
= iso_blkatoff(ip
,0,&bp
)) {
isodir
= (struct iso_directory_record
*)bp
->b_un
.b_addr
;
ip
->iso_extent
= isonum_733(isodir
->extent
);
ip
->i_size
= isonum_733(isodir
->size
);
ip
->iso_start
= isonum_711(isodir
->ext_attr_length
) + ip
->iso_extent
;
* Setup time stamp, attribute
switch (imp
->iso_ftype
) {
default: /* ISO_FTYPE_9660 */
if ((imp
->im_flags
&ISOFSMNT_EXTATT
)
&& isonum_711(isodir
->ext_attr_length
))
iso_blkatoff(ip
,-isonum_711(isodir
->ext_attr_length
),
isofs_defattr(isodir
,ip
,bp2
);
isofs_deftstamp(isodir
,ip
,bp2
);
result
= isofs_rrip_analyze(isodir
,ip
,imp
);
* Initialize the associated vnode
vp
->v_type
= IFTOVT(ip
->inode
.iso_mode
);
if ( vp
->v_type
== VFIFO
) {
extern int (**isofs_fifoop_p
)();
vp
->v_op
= isofs_fifoop_p
;
} else if ( vp
->v_type
== VCHR
|| vp
->v_type
== VBLK
) {
extern int (**isofs_specop_p
)();
* if device, look at device number table for translation
if (dp
= iso_dmap(dev
,ino
,0))
ip
->inode
.iso_rdev
= dp
->d_dev
;
vp
->v_op
= isofs_specop_p
;
if (nvp
= checkalias(vp
, ip
->inode
.iso_rdev
, mntp
)) {
* Reinitialize aliased inode.
bcopy(&ip
->iso_extent
,&iq
->iso_extent
,
(char *)(ip
+ 1) - (char *)&ip
->iso_extent
);
* (This introduces the need of INACTIVE modification)
if (ip
->iso_extent
== imp
->root_extent
)
* Unlock and decrement the reference count of an inode structure.
register struct iso_node
*ip
;
if ((ip
->i_flag
& ILOCKED
) == 0)
* 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("isofs_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("isofs_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
);
* Lock an inode. If its already locked, set the WANT bit and sleep.
register struct iso_node
*ip
;
while (ip
->i_flag
& ILOCKED
) {
if (ip
->i_spare0
== curproc
->p_pid
)
panic("locking against myself");
ip
->i_spare1
= curproc
->p_pid
;
(void) sleep((caddr_t
)ip
, PINOD
);
ip
->i_spare0
= curproc
->p_pid
;
* Unlock an inode. If WANT bit is on, wakeup.
register struct iso_node
*ip
;
if ((ip
->i_flag
& ILOCKED
) == 0)
vprint("iso_iunlock: unlocked inode", ITOV(ip
));
isofs_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
))) {
iso_blkatoff(inop
,-off
* imp
->logical_block_size
,&bp2
);
ap
= (struct iso_extended_attributes
*)bp
->b_un
.b_addr
;
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;
isofs_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
))) {
iso_blkatoff(inop
,-off
* imp
->logical_block_size
,&bp2
);
ap
= (struct iso_extended_attributes
*)bp
->b_un
.b_addr
;
if (isonum_711(ap
->version
) == 1) {
if (!isofs_tstamp_conv17(ap
->ftime
,&inop
->inode
.iso_atime
))
isofs_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_atime
);
if (!isofs_tstamp_conv17(ap
->ctime
,&inop
->inode
.iso_ctime
))
inop
->inode
.iso_ctime
= inop
->inode
.iso_atime
;
if (!isofs_tstamp_conv17(ap
->mtime
,&inop
->inode
.iso_mtime
))
inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
isofs_tstamp_conv7(isodir
->date
,&inop
->inode
.iso_ctime
);
inop
->inode
.iso_atime
= inop
->inode
.iso_ctime
;
inop
->inode
.iso_mtime
= inop
->inode
.iso_ctime
;
isofs_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)
isofs_chars2ui(begin
,len
)
for (rc
= 0; --len
>= 0;) {
isofs_tstamp_conv17(pi
,pu
)
/* year:"0001"-"9999" -> -1900 */
buf
[0] = isofs_chars2ui(pi
,4) - 1900;
/* month: " 1"-"12" -> 1 - 12 */
buf
[1] = isofs_chars2ui(pi
+ 4,2);
/* day: " 1"-"31" -> 1 - 31 */
buf
[2] = isofs_chars2ui(pi
+ 6,2);
/* hour: " 0"-"23" -> 0 - 23 */
buf
[3] = isofs_chars2ui(pi
+ 8,2);
/* minute:" 0"-"59" -> 0 - 59 */
buf
[4] = isofs_chars2ui(pi
+ 10,2);
/* second:" 0"-"59" -> 0 - 59 */
buf
[5] = isofs_chars2ui(pi
+ 12,2);
return isofs_tstamp_conv7(buf
,pu
);
isodirino(inump
,isodir
,imp
)
struct iso_directory_record
*isodir
;
*inump
= (isonum_733(isodir
->extent
) + isonum_711(isodir
->ext_attr_length
))
* imp
->logical_block_size
;