Annotation of XNU/bsd/isofs/cd9660/cd9660_node.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.