|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* $NetBSD: cd9660_node.c,v 1.13 1994/12/24 15:30:07 cgd Exp $ */ ! 23: ! 24: /*- ! 25: * Copyright (c) 1982, 1986, 1989, 1994 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * This code is derived from software contributed to Berkeley ! 29: * by Pace Willisson ([email protected]). The Rock Ridge Extension ! 30: * Support code is derived from software contributed to Berkeley ! 31: * by Atsushi Murai ([email protected]). ! 32: * ! 33: * Redistribution and use in source and binary forms, with or without ! 34: * modification, are permitted provided that the following conditions ! 35: * are met: ! 36: * 1. Redistributions of source code must retain the above copyright ! 37: * notice, this list of conditions and the following disclaimer. ! 38: * 2. Redistributions in binary form must reproduce the above copyright ! 39: * notice, this list of conditions and the following disclaimer in the ! 40: * documentation and/or other materials provided with the distribution. ! 41: * 3. All advertising materials mentioning features or use of this software ! 42: * must display the following acknowledgement: ! 43: * This product includes software developed by the University of ! 44: * California, Berkeley and its contributors. ! 45: * 4. Neither the name of the University nor the names of its contributors ! 46: * may be used to endorse or promote products derived from this software ! 47: * without specific prior written permission. ! 48: * ! 49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 59: * SUCH DAMAGE. ! 60: * ! 61: * @(#)cd9660_node.c 8.5 (Berkeley) 12/5/94 ! 62: ! 63: ! 64: ! 65: * HISTORY ! 66: * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc ! 67: * 17-Feb-98 radar 1669467 - changed lock protocols to use the lock manager - chw ! 68: ! 69: */ ! 70: ! 71: #include <sys/param.h> ! 72: #include <sys/systm.h> ! 73: #include <sys/mount.h> ! 74: #include <sys/proc.h> ! 75: #include <sys/file.h> ! 76: #include <sys/buf.h> ! 77: #include <sys/vnode.h> ! 78: #include <sys/kernel.h> ! 79: #include <sys/malloc.h> ! 80: #include <sys/stat.h> ! 81: ! 82: // radar 1669467 Using the lock manager now so include lock.h ! 83: #include <sys/lock.h> ! 84: ! 85: #include <isofs/cd9660/iso.h> ! 86: #include <isofs/cd9660/cd9660_node.h> ! 87: #include <isofs/cd9660/iso_rrip.h> ! 88: #include <isofs/cd9660/cd9660_mount.h> ! 89: ! 90: /* ! 91: * Structures associated with iso_node caching. ! 92: */ ! 93: struct iso_node **isohashtbl; ! 94: u_long isohash; ! 95: #define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash) ! 96: ! 97: #ifdef ISODEVMAP ! 98: struct iso_node **idvhashtbl; ! 99: u_long idvhash; ! 100: #define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash) ! 101: #endif ! 102: ! 103: /* defined in bsd/ufs/ufs/ufs_inode.c */ ! 104: extern int prtactive; /* 1 => print out reclaim of active vnodes */ ! 105: ! 106: extern void cache_purge (struct vnode *vp); ! 107: ! 108: /* ! 109: * Initialize hash links for inodes and dnodes. ! 110: */ ! 111: int ! 112: cd9660_init() ! 113: { ! 114: ! 115: isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash); ! 116: #ifdef ISODEVMAP ! 117: idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash); ! 118: #endif ! 119: return 0; ! 120: } ! 121: ! 122: #ifdef ISODEVMAP ! 123: /* ! 124: * Enter a new node into the device hash list ! 125: */ ! 126: struct iso_dnode * ! 127: iso_dmap(device, inum, create) ! 128: dev_t device; ! 129: ino_t inum; ! 130: int create; ! 131: { ! 132: register struct iso_dnode **dpp, *dp, *dq; ! 133: ! 134: dpp = &idvhashtbl[DNOHASH(device, inum)]; ! 135: for (dp = *dpp;; dp = dp->d_next) { ! 136: if (dp == NULL) ! 137: return (NULL); ! 138: if (inum == dp->i_number && device == dp->i_dev) ! 139: return (dp); ! 140: ! 141: if (!create) ! 142: return (NULL); ! 143: ! 144: MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE, ! 145: M_WAITOK); ! 146: dp->i_dev = dev; ! 147: dp->i_number = ino; ! 148: ! 149: if (dq = *dpp) ! 150: dq->d_prev = dp->d_next; ! 151: dp->d_next = dq; ! 152: dp->d_prev = dpp; ! 153: *dpp = dp; ! 154: ! 155: return (dp); ! 156: } ! 157: ! 158: void ! 159: iso_dunmap(device) ! 160: dev_t device; ! 161: { ! 162: struct iso_dnode **dpp, *dp, *dq; ! 163: ! 164: for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) { ! 165: for (dp = *dpp; dp != NULL; dp = dq) ! 166: dq = dp->d_next; ! 167: if (device == dp->i_dev) { ! 168: if (dq) ! 169: dq->d_prev = dp->d_prev; ! 170: *dp->d_prev = dq; ! 171: FREE(dp, M_CACHE); ! 172: } ! 173: } ! 174: } ! 175: } ! 176: #endif ! 177: ! 178: /* ! 179: * Use the device/inum pair to find the incore inode, and return a pointer ! 180: * to it. If it is in core, but locked, wait for it. ! 181: */ ! 182: struct vnode * ! 183: cd9660_ihashget(device, inum, p) ! 184: dev_t device; ! 185: ino_t inum; ! 186: struct proc *p; ! 187: { ! 188: register struct iso_node *ip; ! 189: struct vnode *vp; ! 190: ! 191: for (;;) ! 192: for (ip = isohashtbl[INOHASH(device, inum)];; ip = ip->i_next) { ! 193: if (ip == NULL) ! 194: return (NULL); ! 195: if (inum == ip->i_number && device == ip->i_dev) { ! 196: ! 197: // radar 1669467 This is my most dangerous change. I am not waiting for the indoe ! 198: // lock anymore (ufs doesn't, why should we) and I'm worried because ! 199: // there is not lock on the hashtable, but there wasn't before so ! 200: // I'll let it go for now. ! 201: ! 202: vp = ITOV(ip); ! 203: simple_lock(&vp->v_interlock); ! 204: if (!vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY, p)) ! 205: return (vp); ! 206: break; ! 207: } ! 208: } ! 209: /* NOTREACHED */ ! 210: } ! 211: ! 212: /* ! 213: * Insert the inode into the hash table, and return it locked. ! 214: */ ! 215: void ! 216: cd9660_ihashins(ip) ! 217: struct iso_node *ip; ! 218: { ! 219: struct iso_node **ipp, *iq; ! 220: struct proc *p = current_proc(); ! 221: ! 222: // radar 1669467 another change in the locking - chw ! 223: ! 224: /* lock the inode, then put it on the appropriate hash list */ ! 225: lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct slock *)0, p); ! 226: ! 227: ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)]; ! 228: if ((iq = *ipp)) ! 229: iq->i_prev = &ip->i_next; ! 230: ip->i_next = iq; ! 231: ip->i_prev = ipp; ! 232: *ipp = ip; ! 233: } ! 234: ! 235: /* ! 236: * Remove the inode from the hash table. ! 237: */ ! 238: void ! 239: cd9660_ihashrem(ip) ! 240: register struct iso_node *ip; ! 241: { ! 242: register struct iso_node *iq; ! 243: ! 244: if ((iq = ip->i_next)) ! 245: iq->i_prev = ip->i_prev; ! 246: *ip->i_prev = iq; ! 247: #if 1 /* was ifdef DIAGNOSTIC */ ! 248: ip->i_next = NULL; ! 249: ip->i_prev = NULL; ! 250: #endif ! 251: } ! 252: ! 253: /* ! 254: * Last reference to an inode, write the inode out and if necessary, ! 255: * truncate and deallocate the file. ! 256: */ ! 257: int ! 258: cd9660_inactive(ap) ! 259: struct vop_inactive_args /* { ! 260: struct vnode *a_vp; ! 261: } */ *ap; ! 262: { ! 263: struct vnode *vp = ap->a_vp; ! 264: register struct iso_node *ip = VTOI(vp); ! 265: int error = 0; ! 266: ! 267: if (prtactive && vp->v_usecount != 0) ! 268: vprint("cd9660_inactive: pushing active", vp); ! 269: ! 270: ip->i_flag = 0; ! 271: ! 272: // radar 1669467 We need to unlock the inode here. If we don't panics or hangs will ! 273: // ensue. Our callers expect us to take care of this. ! 274: ! 275: VOP_UNLOCK(vp,0,ap->a_p); ! 276: ! 277: /* ! 278: * If we are done with the inode, reclaim it ! 279: * so that it can be reused immediately. ! 280: */ ! 281: if (vp->v_usecount == 0 && ip->inode.iso_mode == 0) ! 282: vgone(vp); ! 283: ! 284: return error; ! 285: } ! 286: ! 287: /* ! 288: * Reclaim an inode so that it can be used for other purposes. ! 289: */ ! 290: int ! 291: cd9660_reclaim(ap) ! 292: struct vop_reclaim_args /* { ! 293: struct vnode *a_vp; ! 294: } */ *ap; ! 295: { ! 296: register struct vnode *vp = ap->a_vp; ! 297: register struct iso_node *ip = VTOI(vp); ! 298: ! 299: if (prtactive && vp->v_usecount != 0) ! 300: vprint("cd9660_reclaim: pushing active", vp); ! 301: /* ! 302: * Remove the inode from its hash chain. ! 303: */ ! 304: cd9660_ihashrem(ip); ! 305: /* ! 306: * Purge old data structures associated with the inode. ! 307: */ ! 308: cache_purge(vp); ! 309: if (ip->i_devvp) { ! 310: vrele(ip->i_devvp); ! 311: ip->i_devvp = 0; ! 312: } ! 313: FREE(vp->v_data, M_ISOFSNODE); ! 314: vp->v_data = NULL; ! 315: return (0); ! 316: } ! 317: ! 318: /* ! 319: * File attributes ! 320: */ ! 321: void ! 322: cd9660_defattr(isodir, inop, bp) ! 323: struct iso_directory_record *isodir; ! 324: struct iso_node *inop; ! 325: struct buf *bp; ! 326: { ! 327: struct buf *bp2 = NULL; ! 328: struct iso_mnt *imp; ! 329: struct iso_extended_attributes *ap = NULL; ! 330: int off; ! 331: ! 332: #if 1 // radar 1669467 - make it pretty ! 333: if ( isonum_711(isodir->flags) & directoryBit ) { ! 334: #else ! 335: if (isonum_711(isodir->flags)&2) { ! 336: #endif // radar 1669467 ! 337: inop->inode.iso_mode = S_IFDIR; ! 338: /* ! 339: * If we return 2, fts() will assume there are no subdirectories ! 340: * (just links for the path and .), so instead we return 1. ! 341: */ ! 342: inop->inode.iso_links = 1; ! 343: } else { ! 344: inop->inode.iso_mode = S_IFREG; ! 345: inop->inode.iso_links = 1; ! 346: } ! 347: if (!bp ! 348: && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT) ! 349: && (off = isonum_711(isodir->ext_attr_length))) { ! 350: VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL, ! 351: &bp2); ! 352: bp = bp2; ! 353: } ! 354: if (bp) { ! 355: ap = (struct iso_extended_attributes *)bp->b_data; ! 356: ! 357: if (isonum_711(ap->version) == 1) { ! 358: if (!(ap->perm[0]&0x40)) ! 359: inop->inode.iso_mode |= VEXEC >> 6; ! 360: if (!(ap->perm[0]&0x10)) ! 361: inop->inode.iso_mode |= VREAD >> 6; ! 362: if (!(ap->perm[0]&4)) ! 363: inop->inode.iso_mode |= VEXEC >> 3; ! 364: if (!(ap->perm[0]&1)) ! 365: inop->inode.iso_mode |= VREAD >> 3; ! 366: if (!(ap->perm[1]&0x40)) ! 367: inop->inode.iso_mode |= VEXEC; ! 368: if (!(ap->perm[1]&0x10)) ! 369: inop->inode.iso_mode |= VREAD; ! 370: inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ ! 371: inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ ! 372: } else ! 373: ap = NULL; ! 374: } ! 375: if (!ap) { ! 376: inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; ! 377: inop->inode.iso_uid = (uid_t)0; ! 378: inop->inode.iso_gid = (gid_t)0; ! 379: } ! 380: if (bp2) ! 381: brelse(bp2); ! 382: } ! 383: ! 384: /* ! 385: * Time stamps ! 386: */ ! 387: void ! 388: cd9660_deftstamp(isodir,inop,bp) ! 389: struct iso_directory_record *isodir; ! 390: struct iso_node *inop; ! 391: struct buf *bp; ! 392: { ! 393: struct buf *bp2 = NULL; ! 394: struct iso_mnt *imp; ! 395: struct iso_extended_attributes *ap = NULL; ! 396: int off; ! 397: ! 398: if (!bp ! 399: && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT) ! 400: && (off = isonum_711(isodir->ext_attr_length))) ! 401: { ! 402: VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL, &bp2); ! 403: bp = bp2; ! 404: } ! 405: if (bp) { ! 406: ap = (struct iso_extended_attributes *)bp->b_data; ! 407: ! 408: if (isonum_711(ap->version) == 1) { ! 409: if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) ! 410: cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); ! 411: if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) ! 412: inop->inode.iso_ctime = inop->inode.iso_atime; ! 413: if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) ! 414: inop->inode.iso_mtime = inop->inode.iso_ctime; ! 415: } else ! 416: ap = NULL; ! 417: } ! 418: if (!ap) { ! 419: cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime); ! 420: inop->inode.iso_atime = inop->inode.iso_ctime; ! 421: inop->inode.iso_mtime = inop->inode.iso_ctime; ! 422: } ! 423: if (bp2) ! 424: brelse(bp2); ! 425: } ! 426: ! 427: int ! 428: cd9660_tstamp_conv7(pi,pu) ! 429: u_char *pi; ! 430: struct timespec *pu; ! 431: { ! 432: int crtime, days; ! 433: int y, m, d, hour, minute, second, tz; ! 434: ! 435: y = pi[0] + 1900; ! 436: m = pi[1]; ! 437: d = pi[2]; ! 438: hour = pi[3]; ! 439: minute = pi[4]; ! 440: second = pi[5]; ! 441: tz = pi[6]; ! 442: ! 443: if (y < 1970) { ! 444: pu->tv_sec = 0; ! 445: pu->tv_nsec = 0; ! 446: return 0; ! 447: } else { ! 448: #ifdef ORIGINAL ! 449: /* computes day number relative to Sept. 19th,1989 */ ! 450: /* don't even *THINK* about changing formula. It works! */ ! 451: days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100; ! 452: #else ! 453: /* ! 454: * Changed :-) to make it relative to Jan. 1st, 1970 ! 455: * and to disambiguate negative division ! 456: */ ! 457: days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239; ! 458: #endif ! 459: crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; ! 460: ! 461: /* timezone offset is unreliable on some disks */ ! 462: if (-48 <= tz && tz <= 52) ! 463: crtime -= tz * 15 * 60; ! 464: } ! 465: pu->tv_sec = crtime; ! 466: pu->tv_nsec = 0; ! 467: return 1; ! 468: } ! 469: ! 470: static u_int ! 471: cd9660_chars2ui(begin,len) ! 472: u_char *begin; ! 473: int len; ! 474: { ! 475: u_int rc; ! 476: ! 477: for (rc = 0; --len >= 0;) { ! 478: rc *= 10; ! 479: rc += *begin++ - '0'; ! 480: } ! 481: return rc; ! 482: } ! 483: ! 484: int ! 485: cd9660_tstamp_conv17(pi,pu) ! 486: u_char *pi; ! 487: struct timespec *pu; ! 488: { ! 489: u_char buf[7]; ! 490: ! 491: /* year:"0001"-"9999" -> -1900 */ ! 492: buf[0] = cd9660_chars2ui(pi,4) - 1900; ! 493: ! 494: /* month: " 1"-"12" -> 1 - 12 */ ! 495: buf[1] = cd9660_chars2ui(pi + 4,2); ! 496: ! 497: /* day: " 1"-"31" -> 1 - 31 */ ! 498: buf[2] = cd9660_chars2ui(pi + 6,2); ! 499: ! 500: /* hour: " 0"-"23" -> 0 - 23 */ ! 501: buf[3] = cd9660_chars2ui(pi + 8,2); ! 502: ! 503: /* minute:" 0"-"59" -> 0 - 59 */ ! 504: buf[4] = cd9660_chars2ui(pi + 10,2); ! 505: ! 506: /* second:" 0"-"59" -> 0 - 59 */ ! 507: buf[5] = cd9660_chars2ui(pi + 12,2); ! 508: ! 509: /* difference of GMT */ ! 510: buf[6] = pi[16]; ! 511: ! 512: return cd9660_tstamp_conv7(buf,pu); ! 513: } ! 514: ! 515: ino_t ! 516: isodirino(isodir, imp) ! 517: struct iso_directory_record *isodir; ! 518: struct iso_mnt *imp; ! 519: { ! 520: ino_t ino; ! 521: ! 522: ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) ! 523: << imp->im_bshift; ! 524: return (ino); ! 525: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.