[BACK]Return to msdosfs_lookup.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / msdosfs

Annotation of src/sys/fs/msdosfs/msdosfs_lookup.c, Revision 1.9.8.1

1.9.8.1 ! ad          1: /*     $NetBSD: msdosfs_lookup.c,v 1.11 2006/12/09 16:11:51 chs Exp $  */
1.1       jdolecek    2:
                      3: /*-
                      4:  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
                      5:  * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
                      6:  * All rights reserved.
                      7:  * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *     This product includes software developed by TooLs GmbH.
                     20:  * 4. The name of TooLs GmbH may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     27:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     28:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     29:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     30:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     31:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     32:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34: /*
                     35:  * Written by Paul Popelka (paulp@uts.amdahl.com)
                     36:  *
                     37:  * You can do anything you want with this software, just don't say you wrote
                     38:  * it, and don't remove this notice.
                     39:  *
                     40:  * This software is provided "as is".
                     41:  *
                     42:  * The author supplies this software to be publicly redistributed on the
                     43:  * understanding that the author is not responsible for the correct
                     44:  * functioning of this software in any circumstances and is not liable for
                     45:  * any damages caused by this software.
                     46:  *
                     47:  * October 1992
                     48:  */
                     49:
                     50: #include <sys/cdefs.h>
1.9.8.1 ! ad         51: __KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.11 2006/12/09 16:11:51 chs Exp $");
1.1       jdolecek   52:
                     53: #include <sys/param.h>
                     54: #include <sys/systm.h>
                     55: #include <sys/namei.h>
                     56: #include <sys/buf.h>
                     57: #include <sys/vnode.h>
                     58: #include <sys/mount.h>
                     59: #include <sys/dirent.h>
1.9       elad       60: #include <sys/kauth.h>
1.1       jdolecek   61:
                     62: #include <fs/msdosfs/bpb.h>
                     63: #include <fs/msdosfs/direntry.h>
                     64: #include <fs/msdosfs/denode.h>
                     65: #include <fs/msdosfs/msdosfsmount.h>
                     66: #include <fs/msdosfs/fat.h>
                     67:
                     68: /*
                     69:  * When we search a directory the blocks containing directory entries are
                     70:  * read and examined.  The directory entries contain information that would
                     71:  * normally be in the inode of a unix filesystem.  This means that some of
                     72:  * a directory's contents may also be in memory resident denodes (sort of
                     73:  * an inode).  This can cause problems if we are searching while some other
                     74:  * process is modifying a directory.  To prevent one process from accessing
                     75:  * incompletely modified directory information we depend upon being the
                     76:  * sole owner of a directory block.  bread/brelse provide this service.
                     77:  * This being the case, when a process modifies a directory it must first
                     78:  * acquire the disk block that contains the directory entry to be modified.
                     79:  * Then update the disk block and the denode, and then write the disk block
                     80:  * out to disk.  This way disk blocks containing directory entries and in
                     81:  * memory denode's will be in synch.
                     82:  */
                     83: int
                     84: msdosfs_lookup(v)
                     85:        void *v;
                     86: {
                     87:        struct vop_lookup_args /* {
                     88:                struct vnode *a_dvp;
                     89:                struct vnode **a_vpp;
                     90:                struct componentname *a_cnp;
                     91:        } */ *ap = v;
                     92:        struct vnode *vdp = ap->a_dvp;
                     93:        struct vnode **vpp = ap->a_vpp;
                     94:        struct componentname *cnp = ap->a_cnp;
                     95:        daddr_t bn;
                     96:        int error;
                     97:        int slotcount;
                     98:        int slotoffset = 0;
                     99:        int frcn;
                    100:        u_long cluster;
                    101:        int blkoff;
                    102:        int diroff;
                    103:        int blsize;
                    104:        int isadir;             /* ~0 if found direntry is a directory   */
                    105:        u_long scn;             /* starting cluster number               */
                    106:        struct vnode *pdp;
                    107:        struct denode *dp;
                    108:        struct denode *tdp;
                    109:        struct msdosfsmount *pmp;
                    110:        struct buf *bp = 0;
                    111:        struct direntry *dep;
                    112:        u_char dosfilename[12];
                    113:        int flags;
                    114:        int nameiop = cnp->cn_nameiop;
                    115:        int wincnt = 1;
                    116:        int chksum = -1, chksum_ok;
                    117:        int olddos = 1;
                    118:
                    119:        flags = cnp->cn_flags;
                    120:
                    121: #ifdef MSDOSFS_DEBUG
                    122:        printf("msdosfs_lookup(): looking for %.*s\n",
                    123:                (int)cnp->cn_namelen, cnp->cn_nameptr);
                    124: #endif
                    125:        dp = VTODE(vdp);
                    126:        pmp = dp->de_pmp;
                    127:        *vpp = NULL;
                    128: #ifdef MSDOSFS_DEBUG
                    129:        printf("msdosfs_lookup(): vdp %p, dp %p, Attr %02x\n",
                    130:            vdp, dp, dp->de_Attributes);
                    131: #endif
                    132:
                    133:        /*
                    134:         * Check accessiblity of directory.
                    135:         */
1.8       christos  136:        if ((error = VOP_ACCESS(vdp, VEXEC, cnp->cn_cred, cnp->cn_lwp)) != 0)
1.1       jdolecek  137:                return (error);
                    138:
                    139:        if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
                    140:            (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
                    141:                return (EROFS);
                    142:
                    143:        /*
                    144:         * We now have a segment name to search for, and a directory to search.
                    145:         *
                    146:         * Before tediously performing a linear scan of the directory,
                    147:         * check the name cache to see if the directory/name pair
                    148:         * we are looking for is known already.
                    149:         */
                    150:        if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
                    151:                return (error);
                    152:
                    153:        /*
                    154:         * If they are going after the . or .. entry in the root directory,
                    155:         * they won't find it.  DOS filesystems don't have them in the root
                    156:         * directory.  So, we fake it. deget() is in on this scam too.
                    157:         */
                    158:        if ((vdp->v_flag & VROOT) && cnp->cn_nameptr[0] == '.' &&
                    159:            (cnp->cn_namelen == 1 ||
                    160:                (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.'))) {
                    161:                isadir = ATTR_DIRECTORY;
                    162:                scn = MSDOSFSROOT;
                    163: #ifdef MSDOSFS_DEBUG
                    164:                printf("msdosfs_lookup(): looking for . or .. in root directory\n");
                    165: #endif
                    166:                cluster = MSDOSFSROOT;
                    167:                blkoff = MSDOSFSROOT_OFS;
                    168:                goto foundroot;
                    169:        }
                    170:
                    171:        switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename,
                    172:            cnp->cn_namelen, 0)) {
                    173:        case 0:
                    174:                return (EINVAL);
                    175:        case 1:
                    176:                break;
                    177:        case 2:
                    178:                wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
                    179:                    cnp->cn_namelen) + 1;
                    180:                break;
                    181:        case 3:
                    182:                olddos = 0;
                    183:                wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
                    184:                    cnp->cn_namelen) + 1;
                    185:                break;
                    186:        }
                    187:        if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
                    188:                wincnt = 1;
                    189:
                    190:        /*
                    191:         * Suppress search for slots unless creating
                    192:         * file and at end of pathname, in which case
                    193:         * we watch for a place to put the new file in
                    194:         * case it doesn't already exist.
                    195:         */
                    196:        slotcount = wincnt;
                    197:        if ((nameiop == CREATE || nameiop == RENAME) &&
                    198:            (flags & ISLASTCN))
                    199:                slotcount = 0;
                    200:
                    201: #ifdef MSDOSFS_DEBUG
                    202:        printf("msdosfs_lookup(): dos filename: %s\n", dosfilename);
                    203: #endif
                    204:        /*
                    205:         * Search the directory pointed at by vdp for the name pointed at
                    206:         * by cnp->cn_nameptr.
                    207:         */
                    208:        tdp = NULL;
                    209:        /*
                    210:         * The outer loop ranges over the clusters that make up the
                    211:         * directory.  Note that the root directory is different from all
                    212:         * other directories.  It has a fixed number of blocks that are not
                    213:         * part of the pool of allocatable clusters.  So, we treat it a
                    214:         * little differently. The root directory starts at "cluster" 0.
                    215:         */
                    216:        diroff = 0;
                    217:        for (frcn = 0; diroff < dp->de_FileSize; frcn++) {
                    218:                if ((error = pcbmap(dp, frcn, &bn, &cluster, &blsize)) != 0) {
                    219:                        if (error == E2BIG)
                    220:                                break;
                    221:                        return (error);
                    222:                }
1.9.8.1 ! ad        223:                error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !           224:                    &bp);
1.1       jdolecek  225:                if (error) {
                    226:                        brelse(bp);
                    227:                        return (error);
                    228:                }
                    229:                for (blkoff = 0; blkoff < blsize;
                    230:                     blkoff += sizeof(struct direntry),
                    231:                     diroff += sizeof(struct direntry)) {
                    232:                        dep = (struct direntry *)(bp->b_data + blkoff);
                    233:                        /*
                    234:                         * If the slot is empty and we are still looking
                    235:                         * for an empty then remember this one.  If the
                    236:                         * slot is not empty then check to see if it
                    237:                         * matches what we are looking for.  If the slot
                    238:                         * has never been filled with anything, then the
                    239:                         * remainder of the directory has never been used,
                    240:                         * so there is no point in searching it.
                    241:                         */
                    242:                        if (dep->deName[0] == SLOT_EMPTY ||
                    243:                            dep->deName[0] == SLOT_DELETED) {
                    244:                                /*
                    245:                                 * Drop memory of previous long matches
                    246:                                 */
                    247:                                chksum = -1;
                    248:
                    249:                                if (slotcount < wincnt) {
                    250:                                        slotcount++;
                    251:                                        slotoffset = diroff;
                    252:                                }
                    253:                                if (dep->deName[0] == SLOT_EMPTY) {
                    254:                                        brelse(bp);
                    255:                                        goto notfound;
                    256:                                }
                    257:                        } else {
                    258:                                /*
                    259:                                 * If there wasn't enough space for our
                    260:                                 * winentries, forget about the empty space
                    261:                                 */
                    262:                                if (slotcount < wincnt)
                    263:                                        slotcount = 0;
                    264:
                    265:                                /*
                    266:                                 * Check for Win95 long filename entry
                    267:                                 */
                    268:                                if (dep->deAttributes == ATTR_WIN95) {
                    269:                                        if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
                    270:                                                continue;
                    271:
                    272:                                        chksum = winChkName((const u_char *)cnp->cn_nameptr,
                    273:                                                            cnp->cn_namelen,
                    274:                                                            (struct winentry *)dep,
                    275:                                                            chksum);
                    276:                                        continue;
                    277:                                }
                    278:
                    279:                                /*
                    280:                                 * Ignore volume labels (anywhere, not just
                    281:                                 * the root directory).
                    282:                                 */
                    283:                                if (dep->deAttributes & ATTR_VOLUME) {
                    284:                                        chksum = -1;
                    285:                                        continue;
                    286:                                }
                    287:
                    288:                                /*
                    289:                                 * Check for a checksum or name match
                    290:                                 */
                    291:                                chksum_ok = (chksum == winChksum(dep->deName));
                    292:                                if (!chksum_ok
                    293:                                    && (!olddos || memcmp(dosfilename, dep->deName, 11))) {
                    294:                                        chksum = -1;
                    295:                                        continue;
                    296:                                }
                    297: #ifdef MSDOSFS_DEBUG
                    298:                                printf("msdosfs_lookup(): match blkoff %d, diroff %d\n",
                    299:                                    blkoff, diroff);
                    300: #endif
                    301:                                /*
                    302:                                 * Remember where this directory
                    303:                                 * entry came from for whoever did
                    304:                                 * this lookup.
                    305:                                 */
                    306:                                dp->de_fndoffset = diroff;
                    307:                                if (chksum_ok && nameiop == RENAME) {
                    308:                                        /*
                    309:                                         * Target had correct long name
                    310:                                         * directory entries, reuse them
                    311:                                         * as needed.
                    312:                                         */
                    313:                                        dp->de_fndcnt = wincnt - 1;
                    314:                                } else {
                    315:                                        /*
                    316:                                         * Long name directory entries
                    317:                                         * not present or corrupt, can only
                    318:                                         * reuse dos directory entry.
                    319:                                         */
                    320:                                        dp->de_fndcnt = 0;
                    321:                                }
                    322:
                    323:                                goto found;
                    324:                        }
                    325:                }       /* for (blkoff = 0; .... */
                    326:                /*
                    327:                 * Release the buffer holding the directory cluster just
                    328:                 * searched.
                    329:                 */
                    330:                brelse(bp);
                    331:        }       /* for (frcn = 0; ; frcn++) */
                    332:
                    333: notfound:
                    334:        /*
                    335:         * We hold no disk buffers at this point.
                    336:         */
                    337:
                    338:        /*
                    339:         * If we get here we didn't find the entry we were looking for. But
                    340:         * that's ok if we are creating or renaming and are at the end of
                    341:         * the pathname and the directory hasn't been removed.
                    342:         */
                    343: #ifdef MSDOSFS_DEBUG
                    344:        printf("msdosfs_lookup(): op %d, refcnt %ld, slotcount %d, slotoffset %d\n",
                    345:            nameiop, dp->de_refcnt, slotcount, slotoffset);
                    346: #endif
                    347:        if ((nameiop == CREATE || nameiop == RENAME) &&
                    348:            (flags & ISLASTCN) && dp->de_refcnt != 0) {
                    349:                /*
                    350:                 * Access for write is interpreted as allowing
                    351:                 * creation of files in the directory.
                    352:                 */
1.8       christos  353:                error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_lwp);
1.1       jdolecek  354:                if (error)
                    355:                        return (error);
                    356:
                    357:                /*
                    358:                 * Fixup the slot description to point to the place where
                    359:                 * we might put the new DOS direntry (putting the Win95
                    360:                 * long name entries before that)
                    361:                 */
                    362:                if (!slotcount) {
                    363:                        slotcount = 1;
                    364:                        slotoffset = diroff;
                    365:                }
                    366:                if (wincnt > slotcount) {
                    367:                        slotoffset +=
                    368:                                sizeof(struct direntry) * (wincnt - slotcount);
                    369:                }
1.4       perry     370:
1.1       jdolecek  371:                /*
                    372:                 * Return an indication of where the new directory
                    373:                 * entry should be put.
                    374:                 */
                    375:                dp->de_fndoffset = slotoffset;
                    376:                dp->de_fndcnt = wincnt - 1;
                    377:
                    378:                /*
                    379:                 * We return with the directory locked, so that
                    380:                 * the parameters we set up above will still be
                    381:                 * valid if we actually decide to do a direnter().
                    382:                 * We return ni_vp == NULL to indicate that the entry
                    383:                 * does not currently exist; we leave a pointer to
                    384:                 * the (locked) directory inode in ndp->ni_dvp.
                    385:                 * The pathname buffer is saved so that the name
                    386:                 * can be obtained later.
                    387:                 *
                    388:                 * NB - if the directory is unlocked, then this
                    389:                 * information cannot be used.
                    390:                 */
                    391:                cnp->cn_flags |= SAVENAME;
                    392:                return (EJUSTRETURN);
                    393:        }
                    394:
1.6       christos  395: #if 0
1.1       jdolecek  396:        /*
                    397:         * Insert name into cache (as non-existent) if appropriate.
1.6       christos  398:         *
                    399:         * XXX Negative caching is broken for msdosfs because the name
                    400:         * cache doesn't understand peculiarities such as case insensitivity
                    401:         * and 8.3 filenames.  Hence, it may not invalidate all negative
                    402:         * entries if a file with this name is later created.
1.7       soda      403:         * e.g. creating a file 'foo' won't invalidate a negative entry
                    404:         * for 'FOO'.
1.1       jdolecek  405:         */
                    406:        if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
                    407:                cache_enter(vdp, *vpp, cnp);
1.6       christos  408: #endif
1.1       jdolecek  409:
                    410:        return (ENOENT);
                    411:
                    412: found:
                    413:        /*
                    414:         * NOTE:  We still have the buffer with matched directory entry at
                    415:         * this point.
                    416:         */
                    417:        isadir = dep->deAttributes & ATTR_DIRECTORY;
                    418:        scn = getushort(dep->deStartCluster);
                    419:        if (FAT32(pmp)) {
                    420:                scn |= getushort(dep->deHighClust) << 16;
                    421:                if (scn == pmp->pm_rootdirblk) {
                    422:                        /*
                    423:                         * There should actually be 0 here.
                    424:                         * Just ignore the error.
                    425:                         */
                    426:                        scn = MSDOSFSROOT;
                    427:                }
                    428:        }
                    429:
                    430:        if (isadir) {
                    431:                cluster = scn;
                    432:                if (cluster == MSDOSFSROOT)
                    433:                        blkoff = MSDOSFSROOT_OFS;
                    434:                else
                    435:                        blkoff = 0;
                    436:        } else if (cluster == MSDOSFSROOT)
                    437:                blkoff = diroff;
                    438:
                    439:        /*
                    440:         * Now release buf to allow deget to read the entry again.
                    441:         * Reserving it here and giving it to deget could result
                    442:         * in a deadlock.
                    443:         */
                    444:        brelse(bp);
                    445:
                    446: foundroot:
                    447:        /*
                    448:         * If we entered at foundroot, then we are looking for the . or ..
                    449:         * entry of the filesystems root directory.  isadir and scn were
                    450:         * setup before jumping here.  And, bp is already null.
                    451:         */
                    452:        if (FAT32(pmp) && scn == MSDOSFSROOT)
                    453:                scn = pmp->pm_rootdirblk;
                    454:
                    455:        /*
                    456:         * If deleting, and at end of pathname, return
                    457:         * parameters which can be used to remove file.
1.9.8.1 ! ad        458:         * Lock the inode, being careful with ".".
1.1       jdolecek  459:         */
                    460:        if (nameiop == DELETE && (flags & ISLASTCN)) {
                    461:                /*
                    462:                 * Don't allow deleting the root.
                    463:                 */
                    464:                if (blkoff == MSDOSFSROOT_OFS)
                    465:                        return EROFS;                   /* really? XXX */
                    466:
                    467:                /*
                    468:                 * Write access to directory required to delete files.
                    469:                 */
1.8       christos  470:                error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_lwp);
1.1       jdolecek  471:                if (error)
                    472:                        return (error);
                    473:
                    474:                /*
                    475:                 * Return pointer to current entry in dp->i_offset.
                    476:                 * Save directory inode pointer in ndp->ni_dvp for dirremove().
                    477:                 */
                    478:                if (dp->de_StartCluster == scn && isadir) {     /* "." */
                    479:                        VREF(vdp);
                    480:                        *vpp = vdp;
                    481:                        return (0);
                    482:                }
                    483:                if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
                    484:                        return (error);
                    485:                *vpp = DETOV(tdp);
                    486:                return (0);
                    487:        }
                    488:
                    489:        /*
                    490:         * If rewriting (RENAME), return the inode and the
                    491:         * information required to rewrite the present directory
                    492:         * Must get inode of directory entry to verify it's a
                    493:         * regular file, or empty directory.
                    494:         */
1.9.8.1 ! ad        495:        if (nameiop == RENAME && (flags & ISLASTCN)) {
1.1       jdolecek  496:
                    497:                if (vdp->v_mount->mnt_flag & MNT_RDONLY)
                    498:                        return (EROFS);
                    499:
                    500:                if (blkoff == MSDOSFSROOT_OFS)
                    501:                        return EROFS;                           /* really? XXX */
                    502:
1.8       christos  503:                error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred, cnp->cn_lwp);
1.1       jdolecek  504:                if (error)
                    505:                        return (error);
                    506:
                    507:                /*
                    508:                 * Careful about locking second inode.
                    509:                 * This can only occur if the target is ".".
                    510:                 */
                    511:                if (dp->de_StartCluster == scn && isadir)
                    512:                        return (EISDIR);
                    513:
                    514:                if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
                    515:                        return (error);
                    516:                *vpp = DETOV(tdp);
                    517:                cnp->cn_flags |= SAVENAME;
                    518:                return (0);
                    519:        }
                    520:
                    521:        /*
                    522:         * Step through the translation in the name.  We do not `vput' the
                    523:         * directory because we may need it again if a symbolic link
                    524:         * is relative to the current directory.  Instead we save it
                    525:         * unlocked as "pdp".  We must get the target inode before unlocking
                    526:         * the directory to insure that the inode will not be removed
                    527:         * before we get it.  We prevent deadlock by always fetching
                    528:         * inodes from the root, moving down the directory tree. Thus
                    529:         * when following backward pointers ".." we must unlock the
                    530:         * parent directory before getting the requested directory.
                    531:         * There is a potential race condition here if both the current
                    532:         * and parent directories are removed before the VFS_VGET for the
                    533:         * inode associated with ".." returns.  We hope that this occurs
                    534:         * infrequently since we cannot avoid this race condition without
                    535:         * implementing a sophisticated deadlock detection algorithm.
                    536:         * Note also that this simple deadlock detection scheme will not
                    537:         * work if the file system has any hard links other than ".."
                    538:         * that point backwards in the directory structure.
                    539:         */
                    540:        pdp = vdp;
                    541:        if (flags & ISDOTDOT) {
                    542:                VOP_UNLOCK(pdp, 0);     /* race to get the inode */
1.9.8.1 ! ad        543:                error = deget(pmp, cluster, blkoff, &tdp);
        !           544:                vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
        !           545:                if (error) {
        !           546:                        return error;
1.1       jdolecek  547:                }
                    548:                *vpp = DETOV(tdp);
                    549:        } else if (dp->de_StartCluster == scn && isadir) {
                    550:                VREF(vdp);      /* we want ourself, ie "." */
                    551:                *vpp = vdp;
                    552:        } else {
                    553:                if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
                    554:                        return (error);
                    555:                *vpp = DETOV(tdp);
                    556:        }
                    557:
                    558:        /*
                    559:         * Insert name into cache if appropriate.
                    560:         */
                    561:        if (cnp->cn_flags & MAKEENTRY)
                    562:                cache_enter(vdp, *vpp, cnp);
                    563:
                    564:        return (0);
                    565: }
                    566:
                    567: /*
                    568:  * dep  - directory entry to copy into the directory
                    569:  * ddep - directory to add to
                    570:  * depp - return the address of the denode for the created directory entry
                    571:  *       if depp != 0
                    572:  * cnp  - componentname needed for Win95 long filenames
                    573:  */
                    574: int
                    575: createde(dep, ddep, depp, cnp)
                    576:        struct denode *dep;
                    577:        struct denode *ddep;
                    578:        struct denode **depp;
                    579:        struct componentname *cnp;
                    580: {
                    581:        int error, rberror;
                    582:        u_long dirclust, clusoffset;
                    583:        u_long fndoffset, havecnt=0, wcnt=1;
                    584:        struct direntry *ndep;
                    585:        struct msdosfsmount *pmp = ddep->de_pmp;
                    586:        struct buf *bp;
                    587:        daddr_t bn;
                    588:        int blsize, i;
                    589:        int async = ddep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC;
                    590:
                    591: #ifdef MSDOSFS_DEBUG
                    592:        printf("createde(dep %p, ddep %p, depp %p, cnp %p)\n",
                    593:            dep, ddep, depp, cnp);
                    594: #endif
                    595:
                    596:        /*
                    597:         * If no space left in the directory then allocate another cluster
                    598:         * and chain it onto the end of the file.  There is one exception
                    599:         * to this.  That is, if the root directory has no more space it
                    600:         * can NOT be expanded.  extendfile() checks for and fails attempts
                    601:         * to extend the root directory.  We just return an error in that
                    602:         * case.
                    603:         */
                    604:        if (ddep->de_fndoffset >= ddep->de_FileSize) {
                    605:                u_long needlen = ddep->de_fndoffset + sizeof(struct direntry)
                    606:                    - ddep->de_FileSize;
                    607:                dirclust = de_clcount(pmp, needlen);
                    608:                if ((error = extendfile(ddep, dirclust, 0, 0, DE_CLEAR)) != 0) {
                    609:                        (void)detrunc(ddep, ddep->de_FileSize, 0, NOCRED, NULL);
                    610:                        goto err_norollback;
                    611:                }
                    612:
                    613:                /*
                    614:                 * Update the size of the directory
                    615:                 */
                    616:                ddep->de_FileSize += de_cn2off(pmp, dirclust);
                    617:        }
                    618:
                    619:        /*
                    620:         * We just read in the cluster with space.  Copy the new directory
                    621:         * entry in.  Then write it to disk. NOTE:  DOS directories
                    622:         * do not get smaller as clusters are emptied.
                    623:         */
                    624:        error = pcbmap(ddep, de_cluster(pmp, ddep->de_fndoffset),
                    625:                       &bn, &dirclust, &blsize);
                    626:        if (error)
                    627:                goto err_norollback;
                    628:        clusoffset = ddep->de_fndoffset;
                    629:        if (dirclust != MSDOSFSROOT)
                    630:                clusoffset &= pmp->pm_crbomask;
1.9.8.1 ! ad        631:        if ((error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !           632:            &bp)) != 0) {
1.1       jdolecek  633:                brelse(bp);
                    634:                goto err_norollback;
                    635:        }
                    636:        ndep = bptoep(pmp, bp, clusoffset);
                    637:
                    638:        DE_EXTERNALIZE(ndep, dep);
                    639:
                    640:        /*
                    641:         * Now write the Win95 long name
                    642:         */
                    643:        if (ddep->de_fndcnt > 0) {
                    644:                u_int8_t chksum = winChksum(ndep->deName);
                    645:                const u_char *un = (const u_char *)cnp->cn_nameptr;
                    646:                int unlen = cnp->cn_namelen;
1.5       christos  647:                u_long xhavecnt;
1.1       jdolecek  648:
                    649:                fndoffset = ddep->de_fndoffset;
1.5       christos  650:                xhavecnt = ddep->de_fndcnt + 1;
1.1       jdolecek  651:
1.5       christos  652:                for(; wcnt < xhavecnt; wcnt++) {
1.1       jdolecek  653:                        if ((fndoffset & pmp->pm_crbomask) == 0) {
                    654:                                /* we should never get here if ddep is root
                    655:                                 * directory */
                    656:
                    657:                                if (async)
                    658:                                        (void) bdwrite(bp);
                    659:                                else if ((error = bwrite(bp)) != 0)
                    660:                                        goto rollback;
                    661:
                    662:                                fndoffset -= sizeof(struct direntry);
                    663:                                error = pcbmap(ddep,
                    664:                                               de_cluster(pmp, fndoffset),
                    665:                                               &bn, 0, &blsize);
                    666:                                if (error)
                    667:                                        goto rollback;
                    668:
1.9.8.1 ! ad        669:                                error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn),
        !           670:                                    blsize, NOCRED, &bp);
1.1       jdolecek  671:                                if (error) {
                    672:                                        brelse(bp);
                    673:                                        goto rollback;
                    674:                                }
                    675:                                ndep = bptoep(pmp, bp,
                    676:                                                fndoffset & pmp->pm_crbomask);
                    677:                        } else {
                    678:                                ndep--;
                    679:                                fndoffset -= sizeof(struct direntry);
                    680:                        }
                    681:                        if (!unix2winfn(un, unlen, (struct winentry *)ndep,
                    682:                                                wcnt, chksum))
                    683:                                break;
                    684:                }
                    685:        }
                    686:
                    687:        if (async)
                    688:                bdwrite(bp);
                    689:        else if ((error = bwrite(bp)) != 0)
                    690:                goto rollback;
                    691:
                    692:        /*
                    693:         * If they want us to return with the denode gotten.
                    694:         */
                    695:        if (depp) {
                    696:                u_long diroffset = clusoffset;
                    697:                if (dep->de_Attributes & ATTR_DIRECTORY) {
                    698:                        dirclust = dep->de_StartCluster;
                    699:                        if (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)
                    700:                                dirclust = MSDOSFSROOT;
                    701:                        if (dirclust == MSDOSFSROOT)
                    702:                                diroffset = MSDOSFSROOT_OFS;
                    703:                        else
                    704:                                diroffset = 0;
                    705:                }
                    706:                return deget(pmp, dirclust, diroffset, depp);
                    707:        }
                    708:
                    709:        return 0;
                    710:
                    711:     rollback:
                    712:        /*
                    713:         * Mark all slots modified so far as deleted. Note that we
                    714:         * can't just call removede(), since directory is not in
                    715:         * consistent state.
                    716:         */
                    717:        fndoffset = ddep->de_fndoffset;
                    718:        rberror = pcbmap(ddep, de_cluster(pmp, fndoffset),
                    719:               &bn, NULL, &blsize);
                    720:        if (rberror)
                    721:                goto err_norollback;
1.9.8.1 ! ad        722:        if ((rberror = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !           723:            &bp)) != 0) {
1.1       jdolecek  724:                brelse(bp);
                    725:                goto err_norollback;
                    726:        }
                    727:        ndep = bptoep(pmp, bp, clusoffset);
                    728:
                    729:        havecnt = ddep->de_fndcnt + 1;
                    730:        for(i=wcnt; i <= havecnt; i++) {
                    731:                /* mark entry as deleted */
                    732:                ndep->deName[0] = SLOT_DELETED;
                    733:
                    734:                if ((fndoffset & pmp->pm_crbomask) == 0) {
                    735:                        /* we should never get here if ddep is root
                    736:                         * directory */
                    737:
                    738:                        if (async)
                    739:                                bdwrite(bp);
                    740:                        else if ((rberror = bwrite(bp)) != 0)
                    741:                                goto err_norollback;
                    742:
                    743:                        fndoffset -= sizeof(struct direntry);
                    744:                        rberror = pcbmap(ddep,
                    745:                                       de_cluster(pmp, fndoffset),
                    746:                                       &bn, 0, &blsize);
                    747:                        if (rberror)
                    748:                                goto err_norollback;
                    749:
1.9.8.1 ! ad        750:                        rberror = bread(pmp->pm_devvp, de_bn2kb(pmp, bn),
        !           751:                            blsize, NOCRED, &bp);
1.1       jdolecek  752:                        if (rberror) {
                    753:                                brelse(bp);
                    754:                                goto err_norollback;
                    755:                        }
                    756:                        ndep = bptoep(pmp, bp, fndoffset);
                    757:                } else {
                    758:                        ndep--;
                    759:                        fndoffset -= sizeof(struct direntry);
                    760:                }
                    761:        }
                    762:
                    763:        /* ignore any further error */
                    764:        if (async)
                    765:                (void) bdwrite(bp);
                    766:        else
                    767:                (void) bwrite(bp);
                    768:
                    769:     err_norollback:
                    770:        return error;
                    771: }
                    772:
                    773: /*
                    774:  * Be sure a directory is empty except for "." and "..". Return 1 if empty,
                    775:  * return 0 if not empty or error.
                    776:  */
                    777: int
                    778: dosdirempty(dep)
                    779:        struct denode *dep;
                    780: {
                    781:        int blsize;
                    782:        int error;
                    783:        u_long cn;
                    784:        daddr_t bn;
                    785:        struct buf *bp;
                    786:        struct msdosfsmount *pmp = dep->de_pmp;
                    787:        struct direntry *dentp;
                    788:
                    789:        /*
                    790:         * Since the filesize field in directory entries for a directory is
                    791:         * zero, we just have to feel our way through the directory until
                    792:         * we hit end of file.
                    793:         */
                    794:        for (cn = 0;; cn++) {
                    795:                if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) {
                    796:                        if (error == E2BIG)
                    797:                                return (1);     /* it's empty */
                    798:                        return (0);
                    799:                }
1.9.8.1 ! ad        800:                error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !           801:                    &bp);
1.1       jdolecek  802:                if (error) {
                    803:                        brelse(bp);
                    804:                        return (0);
                    805:                }
                    806:                for (dentp = (struct direntry *)bp->b_data;
                    807:                     (char *)dentp < bp->b_data + blsize;
                    808:                     dentp++) {
                    809:                        if (dentp->deName[0] != SLOT_DELETED &&
                    810:                            (dentp->deAttributes & ATTR_VOLUME) == 0) {
                    811:                                /*
                    812:                                 * In dos directories an entry whose name
                    813:                                 * starts with SLOT_EMPTY (0) starts the
                    814:                                 * beginning of the unused part of the
                    815:                                 * directory, so we can just return that it
                    816:                                 * is empty.
                    817:                                 */
                    818:                                if (dentp->deName[0] == SLOT_EMPTY) {
                    819:                                        brelse(bp);
                    820:                                        return (1);
                    821:                                }
                    822:                                /*
                    823:                                 * Any names other than "." and ".." in a
                    824:                                 * directory mean it is not empty.
                    825:                                 */
                    826:                                if (memcmp(dentp->deName, ".          ", 11) &&
                    827:                                    memcmp(dentp->deName, "..         ", 11)) {
                    828:                                        brelse(bp);
                    829: #ifdef MSDOSFS_DEBUG
                    830:                                        printf("dosdirempty(): found %.11s, %d, %d\n",
                    831:                                            dentp->deName, dentp->deName[0],
                    832:                                                dentp->deName[1]);
                    833: #endif
                    834:                                        return (0);     /* not empty */
                    835:                                }
                    836:                        }
                    837:                }
                    838:                brelse(bp);
                    839:        }
                    840:        /* NOTREACHED */
                    841: }
                    842:
                    843: /*
                    844:  * Check to see if the directory described by target is in some
                    845:  * subdirectory of source.  This prevents something like the following from
                    846:  * succeeding and leaving a bunch or files and directories orphaned. mv
                    847:  * /a/b/c /a/b/c/d/e/f Where c and f are directories.
                    848:  *
                    849:  * source - the inode for /a/b/c
                    850:  * target - the inode for /a/b/c/d/e/f
                    851:  *
                    852:  * Returns 0 if target is NOT a subdirectory of source.
                    853:  * Otherwise returns a non-zero error number.
                    854:  * The target inode is always unlocked on return.
                    855:  */
                    856: int
                    857: doscheckpath(source, target)
                    858:        struct denode *source;
                    859:        struct denode *target;
                    860: {
                    861:        u_long scn;
                    862:        struct msdosfsmount *pmp;
                    863:        struct direntry *ep;
                    864:        struct denode *dep;
                    865:        struct buf *bp = NULL;
                    866:        int error = 0;
                    867:
                    868:        dep = target;
                    869:        if ((target->de_Attributes & ATTR_DIRECTORY) == 0 ||
                    870:            (source->de_Attributes & ATTR_DIRECTORY) == 0) {
                    871:                error = ENOTDIR;
                    872:                goto out;
                    873:        }
                    874:        if (dep->de_StartCluster == source->de_StartCluster) {
                    875:                error = EEXIST;
                    876:                goto out;
                    877:        }
                    878:        if (dep->de_StartCluster == MSDOSFSROOT)
                    879:                goto out;
                    880:        pmp = dep->de_pmp;
                    881: #ifdef DIAGNOSTIC
                    882:        if (pmp != source->de_pmp)
                    883:                panic("doscheckpath: source and target on different filesystems");
                    884: #endif
                    885:        if (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)
                    886:                goto out;
                    887:
                    888:        for (;;) {
                    889:                if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) {
                    890:                        error = ENOTDIR;
                    891:                        break;
                    892:                }
                    893:                scn = dep->de_StartCluster;
1.9.8.1 ! ad        894:                error = bread(pmp->pm_devvp, de_bn2kb(pmp, cntobn(pmp, scn)),
1.1       jdolecek  895:                              pmp->pm_bpcluster, NOCRED, &bp);
                    896:                if (error)
                    897:                        break;
                    898:
                    899:                ep = (struct direntry *) bp->b_data + 1;
                    900:                if ((ep->deAttributes & ATTR_DIRECTORY) == 0 ||
                    901:                    memcmp(ep->deName, "..         ", 11) != 0) {
                    902:                        error = ENOTDIR;
                    903:                        break;
                    904:                }
                    905:                scn = getushort(ep->deStartCluster);
                    906:                if (FAT32(pmp))
                    907:                        scn |= getushort(ep->deHighClust) << 16;
                    908:
                    909:                if (scn == source->de_StartCluster) {
                    910:                        error = EINVAL;
                    911:                        break;
                    912:                }
                    913:                if (scn == MSDOSFSROOT)
                    914:                        break;
                    915:                if (FAT32(pmp) && scn == pmp->pm_rootdirblk) {
                    916:                        /*
                    917:                         * scn should be 0 in this case,
                    918:                         * but we silently ignore the error.
                    919:                         */
                    920:                        break;
                    921:                }
                    922:
                    923:                vput(DETOV(dep));
                    924:                brelse(bp);
                    925:                bp = NULL;
                    926:                /* NOTE: deget() clears dep on error */
                    927:                if ((error = deget(pmp, scn, 0, &dep)) != 0)
                    928:                        break;
                    929:        }
                    930: out:
                    931:        if (bp)
                    932:                brelse(bp);
                    933:        if (error == ENOTDIR)
                    934:                printf("doscheckpath(): .. not a directory?\n");
                    935:        if (dep != NULL)
                    936:                vput(DETOV(dep));
                    937:        return (error);
                    938: }
                    939:
                    940: /*
                    941:  * Read in the disk block containing the directory entry (dirclu, dirofs)
                    942:  * and return the address of the buf header, and the address of the
                    943:  * directory entry within the block.
                    944:  */
                    945: int
                    946: readep(pmp, dirclust, diroffset, bpp, epp)
                    947:        struct msdosfsmount *pmp;
                    948:        u_long dirclust, diroffset;
                    949:        struct buf **bpp;
                    950:        struct direntry **epp;
                    951: {
                    952:        int error;
                    953:        daddr_t bn;
                    954:        int blsize;
                    955:
                    956:        blsize = pmp->pm_bpcluster;
                    957:        if (dirclust == MSDOSFSROOT
                    958:            && de_blk(pmp, diroffset + blsize) > pmp->pm_rootdirsize)
                    959:                blsize = de_bn2off(pmp, pmp->pm_rootdirsize) & pmp->pm_crbomask;
                    960:        bn = detobn(pmp, dirclust, diroffset);
1.9.8.1 ! ad        961:        if ((error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !           962:            bpp)) != 0) {
1.1       jdolecek  963:                brelse(*bpp);
                    964:                *bpp = NULL;
                    965:                return (error);
                    966:        }
                    967:        if (epp)
                    968:                *epp = bptoep(pmp, *bpp, diroffset);
                    969:        return (0);
                    970: }
                    971:
                    972: /*
                    973:  * Read in the disk block containing the directory entry dep came from and
                    974:  * return the address of the buf header, and the address of the directory
                    975:  * entry within the block.
                    976:  */
                    977: int
                    978: readde(dep, bpp, epp)
                    979:        struct denode *dep;
                    980:        struct buf **bpp;
                    981:        struct direntry **epp;
                    982: {
                    983:        return (readep(dep->de_pmp, dep->de_dirclust, dep->de_diroffset,
                    984:                        bpp, epp));
                    985: }
                    986:
                    987: /*
                    988:  * Remove a directory entry. At this point the file represented by the
                    989:  * directory entry to be removed is still full length until noone has it
                    990:  * open.  When the file no longer being used msdosfs_inactive() is called
                    991:  * and will truncate the file to 0 length.  When the vnode containing the
                    992:  * denode is needed for some other purpose by VFS it will call
                    993:  * msdosfs_reclaim() which will remove the denode from the denode cache.
                    994:  */
                    995: int
                    996: removede(pdep, dep)
                    997:        struct denode *pdep;    /* directory where the entry is removed */
                    998:        struct denode *dep;     /* file to be removed */
                    999: {
                   1000:        int error;
                   1001:        struct direntry *ep;
                   1002:        struct buf *bp;
                   1003:        daddr_t bn;
                   1004:        int blsize;
                   1005:        struct msdosfsmount *pmp = pdep->de_pmp;
                   1006:        u_long offset = pdep->de_fndoffset;
                   1007:        int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC;
                   1008:
                   1009: #ifdef MSDOSFS_DEBUG
                   1010:        printf("removede(): filename %s, dep %p, offset %08lx\n",
                   1011:            dep->de_Name, dep, offset);
                   1012: #endif
                   1013:
                   1014:        dep->de_refcnt--;
                   1015:        offset += sizeof(struct direntry);
                   1016:        do {
                   1017:                offset -= sizeof(struct direntry);
                   1018:                error = pcbmap(pdep, de_cluster(pmp, offset), &bn, 0, &blsize);
                   1019:                if (error)
                   1020:                        return error;
1.9.8.1 ! ad       1021:                error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !          1022:                    &bp);
1.1       jdolecek 1023:                if (error) {
                   1024:                        brelse(bp);
                   1025:                        return error;
                   1026:                }
                   1027:                ep = bptoep(pmp, bp, offset);
                   1028:                /*
                   1029:                 * Check whether, if we came here the second time, i.e.
                   1030:                 * when underflowing into the previous block, the last
                   1031:                 * entry in this block is a longfilename entry, too.
                   1032:                 */
                   1033:                if (ep->deAttributes != ATTR_WIN95
                   1034:                    && offset != pdep->de_fndoffset) {
                   1035:                        brelse(bp);
                   1036:                        break;
                   1037:                }
                   1038:                offset += sizeof(struct direntry);
                   1039:                while (1) {
                   1040:                        /*
                   1041:                         * We are a bit agressive here in that we delete any Win95
                   1042:                         * entries preceding this entry, not just the ones we "own".
                   1043:                         * Since these presumably aren't valid anyway,
                   1044:                         * there should be no harm.
                   1045:                         */
                   1046:                        offset -= sizeof(struct direntry);
                   1047:                        ep--->deName[0] = SLOT_DELETED;
                   1048:                        if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95)
                   1049:                            || !(offset & pmp->pm_crbomask)
                   1050:                            || ep->deAttributes != ATTR_WIN95)
                   1051:                                break;
                   1052:                }
                   1053:                if (async)
                   1054:                        bdwrite(bp);
                   1055:                else if ((error = bwrite(bp)) != 0)
                   1056:                        return error;
                   1057:        } while (!(pmp->pm_flags & MSDOSFSMNT_NOWIN95)
                   1058:            && !(offset & pmp->pm_crbomask)
                   1059:            && offset);
                   1060:        return 0;
                   1061: }
                   1062:
                   1063: /*
                   1064:  * Create a unique DOS name in dvp
                   1065:  */
                   1066: int
                   1067: uniqdosname(dep, cnp, cp)
                   1068:        struct denode *dep;
                   1069:        struct componentname *cnp;
                   1070:        u_char *cp;
                   1071: {
                   1072:        struct msdosfsmount *pmp = dep->de_pmp;
                   1073:        struct direntry *dentp;
                   1074:        int gen;
                   1075:        int blsize;
                   1076:        u_long cn;
                   1077:        daddr_t bn;
                   1078:        struct buf *bp;
                   1079:        int error;
                   1080:
                   1081:        for (gen = 1;; gen++) {
                   1082:                /*
                   1083:                 * Generate DOS name with generation number
                   1084:                 */
                   1085:                if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp,
                   1086:                    cnp->cn_namelen, gen))
                   1087:                        return gen == 1 ? EINVAL : EEXIST;
                   1088:
                   1089:                /*
                   1090:                 * Now look for a dir entry with this exact name
                   1091:                 */
                   1092:                for (cn = error = 0; !error; cn++) {
                   1093:                        if ((error = pcbmap(dep, cn, &bn, 0, &blsize)) != 0) {
                   1094:                                if (error == E2BIG)     /* EOF reached and not found */
                   1095:                                        return 0;
                   1096:                                return error;
                   1097:                        }
1.9.8.1 ! ad       1098:                        error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize,
        !          1099:                            NOCRED, &bp);
1.1       jdolecek 1100:                        if (error) {
                   1101:                                brelse(bp);
                   1102:                                return error;
                   1103:                        }
                   1104:                        for (dentp = (struct direntry *)bp->b_data;
                   1105:                             (char *)dentp < bp->b_data + blsize;
                   1106:                             dentp++) {
                   1107:                                if (dentp->deName[0] == SLOT_EMPTY) {
                   1108:                                        /*
                   1109:                                         * Last used entry and not found
                   1110:                                         */
                   1111:                                        brelse(bp);
                   1112:                                        return 0;
                   1113:                                }
                   1114:                                /*
                   1115:                                 * Ignore volume labels and Win95 entries
                   1116:                                 */
                   1117:                                if (dentp->deAttributes & ATTR_VOLUME)
                   1118:                                        continue;
                   1119:                                if (!memcmp(dentp->deName, cp, 11)) {
                   1120:                                        error = EEXIST;
                   1121:                                        break;
                   1122:                                }
                   1123:                        }
                   1124:                        brelse(bp);
                   1125:                }
                   1126:        }
                   1127: }
                   1128:
                   1129: /*
                   1130:  * Find any Win'95 long filename entry in directory dep
                   1131:  */
                   1132: int
                   1133: findwin95(dep)
                   1134:        struct denode *dep;
                   1135: {
                   1136:        struct msdosfsmount *pmp = dep->de_pmp;
                   1137:        struct direntry *dentp;
                   1138:        int blsize;
                   1139:        u_long cn;
                   1140:        daddr_t bn;
                   1141:        struct buf *bp;
                   1142:
                   1143:        /*
                   1144:         * Read through the directory looking for Win'95 entries
                   1145:         * XXX Note: Error currently handled just as EOF
                   1146:         */
                   1147:        for (cn = 0;; cn++) {
                   1148:                if (pcbmap(dep, cn, &bn, 0, &blsize))
                   1149:                        return 0;
1.9.8.1 ! ad       1150:                if (bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
        !          1151:                    &bp)) {
1.1       jdolecek 1152:                        brelse(bp);
                   1153:                        return 0;
                   1154:                }
                   1155:                for (dentp = (struct direntry *)bp->b_data;
                   1156:                     (char *)dentp < bp->b_data + blsize;
                   1157:                     dentp++) {
                   1158:                        if (dentp->deName[0] == SLOT_EMPTY) {
                   1159:                                /*
                   1160:                                 * Last used entry and not found
                   1161:                                 */
                   1162:                                brelse(bp);
                   1163:                                return 0;
                   1164:                        }
                   1165:                        if (dentp->deName[0] == SLOT_DELETED) {
                   1166:                                /*
                   1167:                                 * Ignore deleted files
                   1168:                                 * Note: might be an indication of Win'95
                   1169:                                 * anyway       XXX
                   1170:                                 */
                   1171:                                continue;
                   1172:                        }
                   1173:                        if (dentp->deAttributes == ATTR_WIN95) {
                   1174:                                brelse(bp);
                   1175:                                return 1;
                   1176:                        }
                   1177:                }
                   1178:                brelse(bp);
                   1179:        }
                   1180: }

CVSweb <webmaster@jp.NetBSD.org>