1/*- 2 * Copyright (c) 1982, 1986, 1989, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cd9660_node.c 8.2 (Berkeley) 1/23/94
| 1/*- 2 * Copyright (c) 1982, 1986, 1989, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cd9660_node.c 8.2 (Berkeley) 1/23/94
|
39 * $Id: cd9660_node.c,v 1.8 1995/01/16 17:03:24 joerg Exp $
| 39 * $Id: cd9660_node.c,v 1.9 1995/02/21 18:41:30 bde Exp $
|
40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/mount.h> 45#include <sys/proc.h> 46#include <sys/file.h> 47#include <sys/buf.h> 48#include <sys/vnode.h> 49#include <sys/kernel.h> 50#include <sys/malloc.h> 51#include <sys/stat.h> 52 53#include <isofs/cd9660/iso.h> 54#include <isofs/cd9660/cd9660_node.h> 55#include <isofs/cd9660/iso_rrip.h> 56 57#define INOHSZ 512 58#if ((INOHSZ&(INOHSZ-1)) == 0) 59#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1)) 60#else 61#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ) 62#endif 63 64union iso_ihead { 65 union iso_ihead *ih_head[2]; 66 struct iso_node *ih_chain[2]; 67} iso_ihead[INOHSZ]; 68 69#ifdef ISODEVMAP 70#define DNOHSZ 64 71#if ((DNOHSZ&(DNOHSZ-1)) == 0) 72#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1)) 73#else 74#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ) 75#endif 76 77union iso_dhead { 78 union iso_dhead *dh_head[2]; 79 struct iso_dnode *dh_chain[2]; 80} iso_dhead[DNOHSZ]; 81#endif 82
| 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/mount.h> 45#include <sys/proc.h> 46#include <sys/file.h> 47#include <sys/buf.h> 48#include <sys/vnode.h> 49#include <sys/kernel.h> 50#include <sys/malloc.h> 51#include <sys/stat.h> 52 53#include <isofs/cd9660/iso.h> 54#include <isofs/cd9660/cd9660_node.h> 55#include <isofs/cd9660/iso_rrip.h> 56 57#define INOHSZ 512 58#if ((INOHSZ&(INOHSZ-1)) == 0) 59#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1)) 60#else 61#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ) 62#endif 63 64union iso_ihead { 65 union iso_ihead *ih_head[2]; 66 struct iso_node *ih_chain[2]; 67} iso_ihead[INOHSZ]; 68 69#ifdef ISODEVMAP 70#define DNOHSZ 64 71#if ((DNOHSZ&(DNOHSZ-1)) == 0) 72#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1)) 73#else 74#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ) 75#endif 76 77union iso_dhead { 78 union iso_dhead *dh_head[2]; 79 struct iso_dnode *dh_chain[2]; 80} iso_dhead[DNOHSZ]; 81#endif 82
|
83int prtactive; /* 1 => print out reclaim of active vnodes */ 84
| |
85/* 86 * Initialize hash links for inodes and dnodes. 87 */ 88int 89cd9660_init() 90{ 91 register int i; 92 register union iso_ihead *ih = iso_ihead; 93#ifdef ISODEVMAP 94 register union iso_dhead *dh = iso_dhead; 95#endif 96 97 for (i = INOHSZ; --i >= 0; ih++) { 98 ih->ih_head[0] = ih; 99 ih->ih_head[1] = ih; 100 } 101#ifdef ISODEVMAP 102 for (i = DNOHSZ; --i >= 0; dh++) { 103 dh->dh_head[0] = dh; 104 dh->dh_head[1] = dh; 105 } 106#endif 107 return (0); 108} 109 110#ifdef ISODEVMAP 111/* 112 * Enter a new node into the device hash list 113 */ 114struct iso_dnode * 115iso_dmap(dev,ino,create) 116 dev_t dev; 117 ino_t ino; 118 int create; 119{ 120 struct iso_dnode *dp; 121 union iso_dhead *dh; 122 123 dh = &iso_dhead[DNOHASH(dev, ino)]; 124 for (dp = dh->dh_chain[0]; 125 dp != (struct iso_dnode *)dh; 126 dp = dp->d_forw) 127 if (ino == dp->i_number && dev == dp->i_dev) 128 return dp; 129 130 if (!create) 131 return (struct iso_dnode *)0; 132 133 MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK); 134 dp->i_dev = dev; 135 dp->i_number = ino; 136 insque(dp,dh); 137 138 return dp; 139} 140 141void 142iso_dunmap(dev) 143 dev_t dev; 144{ 145 struct iso_dnode *dp, *dq; 146 union iso_dhead *dh; 147 148 for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) { 149 for (dp = dh->dh_chain[0]; 150 dp != (struct iso_dnode *)dh; 151 dp = dq) { 152 dq = dp->d_forw; 153 if (dev == dp->i_dev) { 154 remque(dp); 155 FREE(dp,M_CACHE); 156 } 157 } 158 } 159} 160#endif 161 162/* 163 * Look up a ISOFS dinode number to find its incore vnode. 164 * If it is not in core, read it in from the specified device. 165 * If it is in core, wait for the lock bit to clear, then 166 * return the inode locked. Detection and handling of mount 167 * points must be done by the calling routine. 168 */ 169int 170iso_iget(xp, ino, relocated, ipp, isodir) 171 struct iso_node *xp; 172 ino_t ino; 173 int relocated; 174 struct iso_node **ipp; 175 struct iso_directory_record *isodir; 176{ 177 dev_t dev = xp->i_dev; 178 struct mount *mntp = ITOV(xp)->v_mount; 179 register struct iso_node *ip, *iq; 180 register struct vnode *vp; 181#ifdef ISODEVMAP 182 register struct iso_dnode *dp; 183#endif 184 struct vnode *nvp; 185 struct buf *bp = NULL, *bp2 = NULL; 186 union iso_ihead *ih; 187 int error, result; 188 struct iso_mnt *imp; 189 190 ih = &iso_ihead[INOHASH(dev, ino)]; 191loop: 192 for (ip = ih->ih_chain[0]; 193 ip != (struct iso_node *)ih; 194 ip = ip->i_forw) { 195 if (ino != ip->i_number || dev != ip->i_dev) 196 continue; 197 if ((ip->i_flag&ILOCKED) != 0) { 198 ip->i_flag |= IWANT; 199 (void) tsleep((caddr_t)ip, PINOD, "isoigt", 0); 200 goto loop; 201 } 202 if (vget(ITOV(ip), 1)) 203 goto loop; 204 *ipp = ip; 205 return 0; 206 } 207 /* 208 * Allocate a new vnode/iso_node. 209 */ 210 if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) { 211 *ipp = 0; 212 return error; 213 } 214 MALLOC(ip, struct iso_node *, sizeof(struct iso_node), 215 M_ISOFSNODE, M_WAITOK); 216 bzero((caddr_t)ip, sizeof(struct iso_node)); 217 nvp->v_data = ip; 218 ip->i_vnode = nvp; 219 ip->i_flag = 0; 220 ip->i_devvp = 0; 221 ip->i_diroff = 0; 222 ip->i_lockf = 0; 223 224 /* 225 * Put it onto its hash chain and lock it so that other requests for 226 * this inode will block if they arrive while we are sleeping waiting 227 * for old data structures to be purged or for the contents of the 228 * disk portion of this inode to be read. 229 */ 230 ip->i_dev = dev; 231 ip->i_number = ino; 232 insque(ip, ih); 233 ISO_ILOCK(ip); 234 235 imp = VFSTOISOFS (mntp); 236 ip->i_mnt = imp; 237 ip->i_devvp = imp->im_devvp; 238 VREF(ip->i_devvp); 239 240 if (relocated) { 241 /* 242 * On relocated directories we must 243 * read the `.' entry out of a dir. 244 */ 245 ip->iso_start = ino >> imp->im_bshift; 246 if ((error = iso_blkatoff(ip,0,&bp))) { 247 vrele(ip->i_devvp); 248 remque(ip); 249 ip->i_forw = ip; 250 ip->i_back = ip; 251 iso_iput(ip); 252 *ipp = 0; 253 return error; 254 } 255 isodir = (struct iso_directory_record *)bp->b_un.b_addr; 256 } 257 258 ip->iso_extent = isonum_733(isodir->extent); 259 ip->i_size = isonum_733(isodir->size); 260 ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent; 261 262 vp = ITOV(ip); 263 264 /* 265 * Setup time stamp, attribute 266 */ 267 vp->v_type = VNON; 268 switch (imp->iso_ftype) { 269 default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */ 270 if ((imp->im_flags&ISOFSMNT_EXTATT) 271 && isonum_711(isodir->ext_attr_length)) 272 iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length), 273 &bp2); 274 cd9660_defattr(isodir,ip,bp2,imp->iso_ftype ); 275 cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype ); 276 break; 277 case ISO_FTYPE_RRIP: 278 result = cd9660_rrip_analyze(isodir,ip,imp); 279 break; 280 } 281 if (bp2) 282 brelse(bp2); 283 if (bp) 284 brelse(bp); 285 286 /* 287 * Initialize the associated vnode 288 */ 289 vp->v_type = IFTOVT(ip->inode.iso_mode); 290 291 if ( vp->v_type == VFIFO ) {
| 83/* 84 * Initialize hash links for inodes and dnodes. 85 */ 86int 87cd9660_init() 88{ 89 register int i; 90 register union iso_ihead *ih = iso_ihead; 91#ifdef ISODEVMAP 92 register union iso_dhead *dh = iso_dhead; 93#endif 94 95 for (i = INOHSZ; --i >= 0; ih++) { 96 ih->ih_head[0] = ih; 97 ih->ih_head[1] = ih; 98 } 99#ifdef ISODEVMAP 100 for (i = DNOHSZ; --i >= 0; dh++) { 101 dh->dh_head[0] = dh; 102 dh->dh_head[1] = dh; 103 } 104#endif 105 return (0); 106} 107 108#ifdef ISODEVMAP 109/* 110 * Enter a new node into the device hash list 111 */ 112struct iso_dnode * 113iso_dmap(dev,ino,create) 114 dev_t dev; 115 ino_t ino; 116 int create; 117{ 118 struct iso_dnode *dp; 119 union iso_dhead *dh; 120 121 dh = &iso_dhead[DNOHASH(dev, ino)]; 122 for (dp = dh->dh_chain[0]; 123 dp != (struct iso_dnode *)dh; 124 dp = dp->d_forw) 125 if (ino == dp->i_number && dev == dp->i_dev) 126 return dp; 127 128 if (!create) 129 return (struct iso_dnode *)0; 130 131 MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK); 132 dp->i_dev = dev; 133 dp->i_number = ino; 134 insque(dp,dh); 135 136 return dp; 137} 138 139void 140iso_dunmap(dev) 141 dev_t dev; 142{ 143 struct iso_dnode *dp, *dq; 144 union iso_dhead *dh; 145 146 for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) { 147 for (dp = dh->dh_chain[0]; 148 dp != (struct iso_dnode *)dh; 149 dp = dq) { 150 dq = dp->d_forw; 151 if (dev == dp->i_dev) { 152 remque(dp); 153 FREE(dp,M_CACHE); 154 } 155 } 156 } 157} 158#endif 159 160/* 161 * Look up a ISOFS dinode number to find its incore vnode. 162 * If it is not in core, read it in from the specified device. 163 * If it is in core, wait for the lock bit to clear, then 164 * return the inode locked. Detection and handling of mount 165 * points must be done by the calling routine. 166 */ 167int 168iso_iget(xp, ino, relocated, ipp, isodir) 169 struct iso_node *xp; 170 ino_t ino; 171 int relocated; 172 struct iso_node **ipp; 173 struct iso_directory_record *isodir; 174{ 175 dev_t dev = xp->i_dev; 176 struct mount *mntp = ITOV(xp)->v_mount; 177 register struct iso_node *ip, *iq; 178 register struct vnode *vp; 179#ifdef ISODEVMAP 180 register struct iso_dnode *dp; 181#endif 182 struct vnode *nvp; 183 struct buf *bp = NULL, *bp2 = NULL; 184 union iso_ihead *ih; 185 int error, result; 186 struct iso_mnt *imp; 187 188 ih = &iso_ihead[INOHASH(dev, ino)]; 189loop: 190 for (ip = ih->ih_chain[0]; 191 ip != (struct iso_node *)ih; 192 ip = ip->i_forw) { 193 if (ino != ip->i_number || dev != ip->i_dev) 194 continue; 195 if ((ip->i_flag&ILOCKED) != 0) { 196 ip->i_flag |= IWANT; 197 (void) tsleep((caddr_t)ip, PINOD, "isoigt", 0); 198 goto loop; 199 } 200 if (vget(ITOV(ip), 1)) 201 goto loop; 202 *ipp = ip; 203 return 0; 204 } 205 /* 206 * Allocate a new vnode/iso_node. 207 */ 208 if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) { 209 *ipp = 0; 210 return error; 211 } 212 MALLOC(ip, struct iso_node *, sizeof(struct iso_node), 213 M_ISOFSNODE, M_WAITOK); 214 bzero((caddr_t)ip, sizeof(struct iso_node)); 215 nvp->v_data = ip; 216 ip->i_vnode = nvp; 217 ip->i_flag = 0; 218 ip->i_devvp = 0; 219 ip->i_diroff = 0; 220 ip->i_lockf = 0; 221 222 /* 223 * Put it onto its hash chain and lock it so that other requests for 224 * this inode will block if they arrive while we are sleeping waiting 225 * for old data structures to be purged or for the contents of the 226 * disk portion of this inode to be read. 227 */ 228 ip->i_dev = dev; 229 ip->i_number = ino; 230 insque(ip, ih); 231 ISO_ILOCK(ip); 232 233 imp = VFSTOISOFS (mntp); 234 ip->i_mnt = imp; 235 ip->i_devvp = imp->im_devvp; 236 VREF(ip->i_devvp); 237 238 if (relocated) { 239 /* 240 * On relocated directories we must 241 * read the `.' entry out of a dir. 242 */ 243 ip->iso_start = ino >> imp->im_bshift; 244 if ((error = iso_blkatoff(ip,0,&bp))) { 245 vrele(ip->i_devvp); 246 remque(ip); 247 ip->i_forw = ip; 248 ip->i_back = ip; 249 iso_iput(ip); 250 *ipp = 0; 251 return error; 252 } 253 isodir = (struct iso_directory_record *)bp->b_un.b_addr; 254 } 255 256 ip->iso_extent = isonum_733(isodir->extent); 257 ip->i_size = isonum_733(isodir->size); 258 ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent; 259 260 vp = ITOV(ip); 261 262 /* 263 * Setup time stamp, attribute 264 */ 265 vp->v_type = VNON; 266 switch (imp->iso_ftype) { 267 default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */ 268 if ((imp->im_flags&ISOFSMNT_EXTATT) 269 && isonum_711(isodir->ext_attr_length)) 270 iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length), 271 &bp2); 272 cd9660_defattr(isodir,ip,bp2,imp->iso_ftype ); 273 cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype ); 274 break; 275 case ISO_FTYPE_RRIP: 276 result = cd9660_rrip_analyze(isodir,ip,imp); 277 break; 278 } 279 if (bp2) 280 brelse(bp2); 281 if (bp) 282 brelse(bp); 283 284 /* 285 * Initialize the associated vnode 286 */ 287 vp->v_type = IFTOVT(ip->inode.iso_mode); 288 289 if ( vp->v_type == VFIFO ) {
|
292 extern int (**cd9660_fifoop_p)();
| |
293 vp->v_op = cd9660_fifoop_p; 294 } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) {
| 290 vp->v_op = cd9660_fifoop_p; 291 } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) {
|
295 extern int (**cd9660_specop_p)(); 296
| |
297 /* 298 * if device, look at device number table for translation 299 */ 300#ifdef ISODEVMAP 301 if (dp = iso_dmap(dev,ino,0)) 302 ip->inode.iso_rdev = dp->d_dev; 303#endif 304 vp->v_op = cd9660_specop_p; 305 if ((nvp = checkalias(vp, ip->inode.iso_rdev, mntp))) { 306 /* 307 * Reinitialize aliased inode. 308 */ 309 vp = nvp; 310 iq = VTOI(vp); 311 iq->i_vnode = vp; 312 iq->i_flag = 0; 313 ISO_ILOCK(iq); 314 iq->i_dev = dev; 315 iq->i_number = ino; 316 iq->i_mnt = ip->i_mnt; 317 bcopy(&ip->iso_extent,&iq->iso_extent, 318 (char *)(ip + 1) - (char *)&ip->iso_extent); 319 insque(iq, ih); 320 /* 321 * Discard unneeded vnode 322 * (This introduces the need of INACTIVE modification) 323 */ 324 ip->inode.iso_mode = 0; 325 iso_iput(ip); 326 ip = iq; 327 } 328 } 329 330 if (ip->iso_extent == imp->root_extent) 331 vp->v_flag |= VROOT; 332 333 *ipp = ip; 334 return 0; 335} 336 337/* 338 * Unlock and decrement the reference count of an inode structure. 339 */ 340int 341iso_iput(ip) 342 register struct iso_node *ip; 343{ 344 345 if ((ip->i_flag & ILOCKED) == 0) 346 panic("iso_iput"); 347 ISO_IUNLOCK(ip); 348 vrele(ITOV(ip)); 349 return (0); 350} 351 352/* 353 * Last reference to an inode, write the inode out and if necessary, 354 * truncate and deallocate the file. 355 */ 356int 357cd9660_inactive(ap) 358 struct vop_inactive_args /* { 359 struct vnode *a_vp; 360 } */ *ap; 361{ 362 struct vnode *vp = ap->a_vp; 363 register struct iso_node *ip = VTOI(vp); 364 int error = 0; 365 366 if (prtactive && vp->v_usecount != 0) 367 vprint("cd9660_inactive: pushing active", vp); 368 369 ip->i_flag = 0; 370 /* 371 * If we are done with the inode, reclaim it 372 * so that it can be reused immediately. 373 */ 374 if (vp->v_usecount == 0 && ip->inode.iso_mode == 0) 375 vgone(vp); 376 return error; 377} 378 379/* 380 * Reclaim an inode so that it can be used for other purposes. 381 */ 382int 383cd9660_reclaim(ap) 384 struct vop_reclaim_args /* { 385 struct vnode *a_vp; 386 } */ *ap; 387{ 388 register struct vnode *vp = ap->a_vp; 389 register struct iso_node *ip = VTOI(vp); 390 391 if (prtactive && vp->v_usecount != 0) 392 vprint("cd9660_reclaim: pushing active", vp); 393 /* 394 * Remove the inode from its hash chain. 395 */ 396 remque(ip); 397 ip->i_forw = ip; 398 ip->i_back = ip; 399 /* 400 * Purge old data structures associated with the inode. 401 */ 402 cache_purge(vp); 403 if (ip->i_devvp) { 404 vrele(ip->i_devvp); 405 ip->i_devvp = 0; 406 } 407 FREE(vp->v_data, M_ISOFSNODE); 408 vp->v_data = NULL; 409 return 0; 410} 411 412/* 413 * Lock an inode. If its already locked, set the WANT bit and sleep. 414 */ 415int 416iso_ilock(ip) 417 register struct iso_node *ip; 418{ 419 420 while (ip->i_flag & ILOCKED) { 421 ip->i_flag |= IWANT; 422 if (ip->i_spare0 == curproc->p_pid) 423 panic("locking against myself"); 424 ip->i_spare1 = curproc->p_pid; 425 (void) tsleep((caddr_t)ip, PINOD, "isoilk", 0); 426 } 427 ip->i_spare1 = 0; 428 ip->i_spare0 = curproc->p_pid; 429 ip->i_flag |= ILOCKED; 430 return (0); 431} 432 433/* 434 * Unlock an inode. If WANT bit is on, wakeup. 435 */ 436int 437iso_iunlock(ip) 438 register struct iso_node *ip; 439{ 440 441 if ((ip->i_flag & ILOCKED) == 0) 442 vprint("iso_iunlock: unlocked inode", ITOV(ip)); 443 ip->i_spare0 = 0; 444 ip->i_flag &= ~ILOCKED; 445 if (ip->i_flag&IWANT) { 446 ip->i_flag &= ~IWANT; 447 wakeup((caddr_t)ip); 448 } 449 return (0); 450} 451 452/* 453 * File attributes 454 */ 455void 456cd9660_defattr(isodir,inop,bp,ftype) 457 struct iso_directory_record *isodir; 458 struct iso_node *inop; 459 struct buf *bp; 460 enum ISO_FTYPE ftype; 461{ 462 struct buf *bp2 = NULL; 463 struct iso_mnt *imp; 464 struct iso_extended_attributes *ap = NULL; 465 int off; 466 467 /* high sierra does not have timezone data, flag is one byte ahead */ 468 if (isonum_711(ftype == ISO_FTYPE_HIGH_SIERRA? 469 &isodir->date[6]: isodir->flags)&2) { 470 inop->inode.iso_mode = S_IFDIR; 471 /* 472 * If we return 2, fts() will assume there are no subdirectories 473 * (just links for the path and .), so instead we return 1. 474 */ 475 inop->inode.iso_links = 1; 476 } else { 477 inop->inode.iso_mode = S_IFREG; 478 inop->inode.iso_links = 1; 479 } 480 if (!bp 481 && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 482 && (off = isonum_711(isodir->ext_attr_length))) { 483 iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 484 bp = bp2; 485 } 486 if (bp) { 487 ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 488 489 if (isonum_711(ap->version) == 1) { 490 if (!(ap->perm[0]&0x40)) 491 inop->inode.iso_mode |= VEXEC >> 6; 492 if (!(ap->perm[0]&0x10)) 493 inop->inode.iso_mode |= VREAD >> 6; 494 if (!(ap->perm[0]&4)) 495 inop->inode.iso_mode |= VEXEC >> 3; 496 if (!(ap->perm[0]&1)) 497 inop->inode.iso_mode |= VREAD >> 3; 498 if (!(ap->perm[1]&0x40)) 499 inop->inode.iso_mode |= VEXEC; 500 if (!(ap->perm[1]&0x10)) 501 inop->inode.iso_mode |= VREAD; 502 inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 503 inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 504 } else 505 ap = NULL; 506 } 507 if (!ap) { 508 inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 509 inop->inode.iso_uid = (uid_t)0; 510 inop->inode.iso_gid = (gid_t)0; 511 } 512 if (bp2) 513 brelse(bp2); 514} 515 516/* 517 * Time stamps 518 */ 519void 520cd9660_deftstamp(isodir,inop,bp,ftype) 521 struct iso_directory_record *isodir; 522 struct iso_node *inop; 523 struct buf *bp; 524 enum ISO_FTYPE ftype; 525{ 526 struct buf *bp2 = NULL; 527 struct iso_mnt *imp; 528 struct iso_extended_attributes *ap = NULL; 529 int off; 530 531 if (!bp 532 && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 533 && (off = isonum_711(isodir->ext_attr_length))) { 534 iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 535 bp = bp2; 536 } 537 if (bp) { 538 ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 539 540 if (ftype != ISO_FTYPE_HIGH_SIERRA 541 && isonum_711(ap->version) == 1) { 542 if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 543 cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 544 if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 545 inop->inode.iso_ctime = inop->inode.iso_atime; 546 if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 547 inop->inode.iso_mtime = inop->inode.iso_ctime; 548 } else 549 ap = NULL; 550 } 551 if (!ap) { 552 cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime,ftype); 553 inop->inode.iso_atime = inop->inode.iso_ctime; 554 inop->inode.iso_mtime = inop->inode.iso_ctime; 555 } 556 if (bp2) 557 brelse(bp2); 558} 559 560int 561cd9660_tstamp_conv7(pi,pu,ftype) 562char *pi; 563struct timespec *pu; 564enum ISO_FTYPE ftype; 565{ 566 int crtime, days; 567 int y, m, d, hour, minute, second, tz; 568 569 y = pi[0] + 1900; 570 m = pi[1]; 571 d = pi[2]; 572 hour = pi[3]; 573 minute = pi[4]; 574 second = pi[5]; 575 if(ftype != ISO_FTYPE_HIGH_SIERRA) 576 tz = pi[6]; 577 else 578 /* original high sierra misses timezone data */ 579 tz = 0; 580 581 if (y < 1970) { 582 pu->ts_sec = 0; 583 pu->ts_nsec = 0; 584 return 0; 585 } else { 586#ifdef ORIGINAL 587 /* computes day number relative to Sept. 19th,1989 */ 588 /* don't even *THINK* about changing formula. It works! */ 589 days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100; 590#else 591 /* 592 * Changed :-) to make it relative to Jan. 1st, 1970 593 * and to disambiguate negative division 594 */ 595 days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239; 596#endif 597 crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 598 599 /* timezone offset is unreliable on some disks */ 600 if (-48 <= tz && tz <= 52) 601 crtime -= tz * 15 * 60; 602 } 603 pu->ts_sec = crtime; 604 pu->ts_nsec = 0; 605 return 1; 606} 607 608static unsigned 609cd9660_chars2ui(begin,len) 610 unsigned char *begin; 611 int len; 612{ 613 unsigned rc; 614 615 for (rc = 0; --len >= 0;) { 616 rc *= 10; 617 rc += *begin++ - '0'; 618 } 619 return rc; 620} 621 622int 623cd9660_tstamp_conv17(pi,pu) 624 unsigned char *pi; 625 struct timespec *pu; 626{ 627 unsigned char buf[7]; 628 629 /* year:"0001"-"9999" -> -1900 */ 630 buf[0] = cd9660_chars2ui(pi,4) - 1900; 631 632 /* month: " 1"-"12" -> 1 - 12 */ 633 buf[1] = cd9660_chars2ui(pi + 4,2); 634 635 /* day: " 1"-"31" -> 1 - 31 */ 636 buf[2] = cd9660_chars2ui(pi + 6,2); 637 638 /* hour: " 0"-"23" -> 0 - 23 */ 639 buf[3] = cd9660_chars2ui(pi + 8,2); 640 641 /* minute:" 0"-"59" -> 0 - 59 */ 642 buf[4] = cd9660_chars2ui(pi + 10,2); 643 644 /* second:" 0"-"59" -> 0 - 59 */ 645 buf[5] = cd9660_chars2ui(pi + 12,2); 646 647 /* difference of GMT */ 648 buf[6] = pi[16]; 649 650 return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT); 651} 652 653void 654isodirino(inump,isodir,imp) 655 ino_t *inump; 656 struct iso_directory_record *isodir; 657 struct iso_mnt *imp; 658{ 659 *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 660 * imp->logical_block_size; 661}
| 292 /* 293 * if device, look at device number table for translation 294 */ 295#ifdef ISODEVMAP 296 if (dp = iso_dmap(dev,ino,0)) 297 ip->inode.iso_rdev = dp->d_dev; 298#endif 299 vp->v_op = cd9660_specop_p; 300 if ((nvp = checkalias(vp, ip->inode.iso_rdev, mntp))) { 301 /* 302 * Reinitialize aliased inode. 303 */ 304 vp = nvp; 305 iq = VTOI(vp); 306 iq->i_vnode = vp; 307 iq->i_flag = 0; 308 ISO_ILOCK(iq); 309 iq->i_dev = dev; 310 iq->i_number = ino; 311 iq->i_mnt = ip->i_mnt; 312 bcopy(&ip->iso_extent,&iq->iso_extent, 313 (char *)(ip + 1) - (char *)&ip->iso_extent); 314 insque(iq, ih); 315 /* 316 * Discard unneeded vnode 317 * (This introduces the need of INACTIVE modification) 318 */ 319 ip->inode.iso_mode = 0; 320 iso_iput(ip); 321 ip = iq; 322 } 323 } 324 325 if (ip->iso_extent == imp->root_extent) 326 vp->v_flag |= VROOT; 327 328 *ipp = ip; 329 return 0; 330} 331 332/* 333 * Unlock and decrement the reference count of an inode structure. 334 */ 335int 336iso_iput(ip) 337 register struct iso_node *ip; 338{ 339 340 if ((ip->i_flag & ILOCKED) == 0) 341 panic("iso_iput"); 342 ISO_IUNLOCK(ip); 343 vrele(ITOV(ip)); 344 return (0); 345} 346 347/* 348 * Last reference to an inode, write the inode out and if necessary, 349 * truncate and deallocate the file. 350 */ 351int 352cd9660_inactive(ap) 353 struct vop_inactive_args /* { 354 struct vnode *a_vp; 355 } */ *ap; 356{ 357 struct vnode *vp = ap->a_vp; 358 register struct iso_node *ip = VTOI(vp); 359 int error = 0; 360 361 if (prtactive && vp->v_usecount != 0) 362 vprint("cd9660_inactive: pushing active", vp); 363 364 ip->i_flag = 0; 365 /* 366 * If we are done with the inode, reclaim it 367 * so that it can be reused immediately. 368 */ 369 if (vp->v_usecount == 0 && ip->inode.iso_mode == 0) 370 vgone(vp); 371 return error; 372} 373 374/* 375 * Reclaim an inode so that it can be used for other purposes. 376 */ 377int 378cd9660_reclaim(ap) 379 struct vop_reclaim_args /* { 380 struct vnode *a_vp; 381 } */ *ap; 382{ 383 register struct vnode *vp = ap->a_vp; 384 register struct iso_node *ip = VTOI(vp); 385 386 if (prtactive && vp->v_usecount != 0) 387 vprint("cd9660_reclaim: pushing active", vp); 388 /* 389 * Remove the inode from its hash chain. 390 */ 391 remque(ip); 392 ip->i_forw = ip; 393 ip->i_back = ip; 394 /* 395 * Purge old data structures associated with the inode. 396 */ 397 cache_purge(vp); 398 if (ip->i_devvp) { 399 vrele(ip->i_devvp); 400 ip->i_devvp = 0; 401 } 402 FREE(vp->v_data, M_ISOFSNODE); 403 vp->v_data = NULL; 404 return 0; 405} 406 407/* 408 * Lock an inode. If its already locked, set the WANT bit and sleep. 409 */ 410int 411iso_ilock(ip) 412 register struct iso_node *ip; 413{ 414 415 while (ip->i_flag & ILOCKED) { 416 ip->i_flag |= IWANT; 417 if (ip->i_spare0 == curproc->p_pid) 418 panic("locking against myself"); 419 ip->i_spare1 = curproc->p_pid; 420 (void) tsleep((caddr_t)ip, PINOD, "isoilk", 0); 421 } 422 ip->i_spare1 = 0; 423 ip->i_spare0 = curproc->p_pid; 424 ip->i_flag |= ILOCKED; 425 return (0); 426} 427 428/* 429 * Unlock an inode. If WANT bit is on, wakeup. 430 */ 431int 432iso_iunlock(ip) 433 register struct iso_node *ip; 434{ 435 436 if ((ip->i_flag & ILOCKED) == 0) 437 vprint("iso_iunlock: unlocked inode", ITOV(ip)); 438 ip->i_spare0 = 0; 439 ip->i_flag &= ~ILOCKED; 440 if (ip->i_flag&IWANT) { 441 ip->i_flag &= ~IWANT; 442 wakeup((caddr_t)ip); 443 } 444 return (0); 445} 446 447/* 448 * File attributes 449 */ 450void 451cd9660_defattr(isodir,inop,bp,ftype) 452 struct iso_directory_record *isodir; 453 struct iso_node *inop; 454 struct buf *bp; 455 enum ISO_FTYPE ftype; 456{ 457 struct buf *bp2 = NULL; 458 struct iso_mnt *imp; 459 struct iso_extended_attributes *ap = NULL; 460 int off; 461 462 /* high sierra does not have timezone data, flag is one byte ahead */ 463 if (isonum_711(ftype == ISO_FTYPE_HIGH_SIERRA? 464 &isodir->date[6]: isodir->flags)&2) { 465 inop->inode.iso_mode = S_IFDIR; 466 /* 467 * If we return 2, fts() will assume there are no subdirectories 468 * (just links for the path and .), so instead we return 1. 469 */ 470 inop->inode.iso_links = 1; 471 } else { 472 inop->inode.iso_mode = S_IFREG; 473 inop->inode.iso_links = 1; 474 } 475 if (!bp 476 && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 477 && (off = isonum_711(isodir->ext_attr_length))) { 478 iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 479 bp = bp2; 480 } 481 if (bp) { 482 ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 483 484 if (isonum_711(ap->version) == 1) { 485 if (!(ap->perm[0]&0x40)) 486 inop->inode.iso_mode |= VEXEC >> 6; 487 if (!(ap->perm[0]&0x10)) 488 inop->inode.iso_mode |= VREAD >> 6; 489 if (!(ap->perm[0]&4)) 490 inop->inode.iso_mode |= VEXEC >> 3; 491 if (!(ap->perm[0]&1)) 492 inop->inode.iso_mode |= VREAD >> 3; 493 if (!(ap->perm[1]&0x40)) 494 inop->inode.iso_mode |= VEXEC; 495 if (!(ap->perm[1]&0x10)) 496 inop->inode.iso_mode |= VREAD; 497 inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 498 inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 499 } else 500 ap = NULL; 501 } 502 if (!ap) { 503 inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 504 inop->inode.iso_uid = (uid_t)0; 505 inop->inode.iso_gid = (gid_t)0; 506 } 507 if (bp2) 508 brelse(bp2); 509} 510 511/* 512 * Time stamps 513 */ 514void 515cd9660_deftstamp(isodir,inop,bp,ftype) 516 struct iso_directory_record *isodir; 517 struct iso_node *inop; 518 struct buf *bp; 519 enum ISO_FTYPE ftype; 520{ 521 struct buf *bp2 = NULL; 522 struct iso_mnt *imp; 523 struct iso_extended_attributes *ap = NULL; 524 int off; 525 526 if (!bp 527 && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 528 && (off = isonum_711(isodir->ext_attr_length))) { 529 iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 530 bp = bp2; 531 } 532 if (bp) { 533 ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 534 535 if (ftype != ISO_FTYPE_HIGH_SIERRA 536 && isonum_711(ap->version) == 1) { 537 if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 538 cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 539 if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 540 inop->inode.iso_ctime = inop->inode.iso_atime; 541 if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 542 inop->inode.iso_mtime = inop->inode.iso_ctime; 543 } else 544 ap = NULL; 545 } 546 if (!ap) { 547 cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime,ftype); 548 inop->inode.iso_atime = inop->inode.iso_ctime; 549 inop->inode.iso_mtime = inop->inode.iso_ctime; 550 } 551 if (bp2) 552 brelse(bp2); 553} 554 555int 556cd9660_tstamp_conv7(pi,pu,ftype) 557char *pi; 558struct timespec *pu; 559enum ISO_FTYPE ftype; 560{ 561 int crtime, days; 562 int y, m, d, hour, minute, second, tz; 563 564 y = pi[0] + 1900; 565 m = pi[1]; 566 d = pi[2]; 567 hour = pi[3]; 568 minute = pi[4]; 569 second = pi[5]; 570 if(ftype != ISO_FTYPE_HIGH_SIERRA) 571 tz = pi[6]; 572 else 573 /* original high sierra misses timezone data */ 574 tz = 0; 575 576 if (y < 1970) { 577 pu->ts_sec = 0; 578 pu->ts_nsec = 0; 579 return 0; 580 } else { 581#ifdef ORIGINAL 582 /* computes day number relative to Sept. 19th,1989 */ 583 /* don't even *THINK* about changing formula. It works! */ 584 days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100; 585#else 586 /* 587 * Changed :-) to make it relative to Jan. 1st, 1970 588 * and to disambiguate negative division 589 */ 590 days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239; 591#endif 592 crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 593 594 /* timezone offset is unreliable on some disks */ 595 if (-48 <= tz && tz <= 52) 596 crtime -= tz * 15 * 60; 597 } 598 pu->ts_sec = crtime; 599 pu->ts_nsec = 0; 600 return 1; 601} 602 603static unsigned 604cd9660_chars2ui(begin,len) 605 unsigned char *begin; 606 int len; 607{ 608 unsigned rc; 609 610 for (rc = 0; --len >= 0;) { 611 rc *= 10; 612 rc += *begin++ - '0'; 613 } 614 return rc; 615} 616 617int 618cd9660_tstamp_conv17(pi,pu) 619 unsigned char *pi; 620 struct timespec *pu; 621{ 622 unsigned char buf[7]; 623 624 /* year:"0001"-"9999" -> -1900 */ 625 buf[0] = cd9660_chars2ui(pi,4) - 1900; 626 627 /* month: " 1"-"12" -> 1 - 12 */ 628 buf[1] = cd9660_chars2ui(pi + 4,2); 629 630 /* day: " 1"-"31" -> 1 - 31 */ 631 buf[2] = cd9660_chars2ui(pi + 6,2); 632 633 /* hour: " 0"-"23" -> 0 - 23 */ 634 buf[3] = cd9660_chars2ui(pi + 8,2); 635 636 /* minute:" 0"-"59" -> 0 - 59 */ 637 buf[4] = cd9660_chars2ui(pi + 10,2); 638 639 /* second:" 0"-"59" -> 0 - 59 */ 640 buf[5] = cd9660_chars2ui(pi + 12,2); 641 642 /* difference of GMT */ 643 buf[6] = pi[16]; 644 645 return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT); 646} 647 648void 649isodirino(inump,isodir,imp) 650 ino_t *inump; 651 struct iso_directory_record *isodir; 652 struct iso_mnt *imp; 653{ 654 *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 655 * imp->logical_block_size; 656}
|