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

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

unix.superglobalmegacorp.com

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