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