Annotation of Net2/pcfs/pcfs_fat.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  Written by Paul Popelka ([email protected])
                      3:  *
                      4:  *  You can do anything you want with this software,
                      5:  *    just don't say you wrote it,
                      6:  *    and don't remove this notice.
                      7:  *
                      8:  *  This software is provided "as is".
                      9:  *
                     10:  *  The author supplies this software to be publicly
                     11:  *  redistributed on the understanding that the author
                     12:  *  is not responsible for the correct functioning of
                     13:  *  this software in any circumstances and is not liable
                     14:  *  for any damages caused by this software.
                     15:  *
                     16:  *  October 1992
                     17:  *
                     18:  *     pcfs_fat.c,v 1.3 1993/05/20 03:34:12 cgd Exp
                     19:  */
                     20: 
                     21: /*
                     22:  *  kernel include files.
                     23:  */
                     24: #include "param.h"
                     25: #include "systm.h"
                     26: #include "buf.h"
                     27: #include "file.h"
                     28: #include "namei.h"
                     29: #include "mount.h"     /* to define statfs structure */
                     30: #include "vnode.h"     /* to define vattr structure */
                     31: #include "errno.h"
                     32: 
                     33: /*
                     34:  *  pcfs include files.
                     35:  */
                     36: #include "bpb.h"
                     37: #include "pcfsmount.h"
                     38: #include "direntry.h"
                     39: #include "denode.h"
                     40: #include "fat.h"
                     41: 
                     42: /*
                     43:  *  Fat cache stats.
                     44:  */
                     45: int fc_fileextends;            /* # of file extends                    */
                     46: int fc_lfcempty;               /* # of time last file cluster cache entry
                     47:                                 * was empty */
                     48: int fc_bmapcalls;              /* # of times pcbmap was called         */
                     49: #define        LMMAX   20
                     50: int fc_lmdistance[LMMAX];      /* counters for how far off the last cluster
                     51:                                 * mapped entry was. */
                     52: int fc_largedistance;          /* off by more than LMMAX               */
                     53: 
                     54: /* Byte offset in FAT on filesystem pmp, cluster cn */
                     55: #define        FATOFS(pmp, cn) (FAT12(pmp) ? (cn) * 3 / 2 : (cn) * 2)
                     56: 
                     57: 
                     58: static void fatblock (pmp, ofs, bnp, sizep, bop)
                     59:        struct pcfsmount *pmp;
                     60:        u_long ofs;
                     61:        u_long *bnp;
                     62:        u_long *sizep;
                     63:        u_long *bop;
                     64: {
                     65:        u_long bn, size;
                     66: 
                     67:        bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
                     68:        size = min (pmp->pm_fatblocksec, pmp->pm_FATsecs - bn)
                     69:                * pmp->pm_BytesPerSec;
                     70:        bn += pmp->pm_fatblk;
                     71:        if (bnp)
                     72:                *bnp = bn;
                     73:        if (sizep)
                     74:                *sizep = size;
                     75:        if (bop)
                     76:                *bop = ofs % pmp->pm_fatblocksize;
                     77: }
                     78: 
                     79: /*
                     80:  *  Map the logical cluster number of a file into
                     81:  *  a physical disk sector that is filesystem relative.
                     82:  *  dep - address of denode representing the file of interest
                     83:  *  findcn - file relative cluster whose filesystem relative
                     84:  *    cluster number and/or block number are/is to be found
                     85:  *  bnp - address of where to place the file system relative
                     86:  *    block number.  If this pointer is null then don't return
                     87:  *    this quantity.
                     88:  *  cnp - address of where to place the file system relative
                     89:  *    cluster number.  If this pointer is null then don't return
                     90:  *    this quantity.
                     91:  *  NOTE:
                     92:  *    Either bnp or cnp must be non-null.
                     93:  *    This function has one side effect.  If the requested
                     94:  *    file relative cluster is beyond the end of file, then
                     95:  *    the actual number of clusters in the file is returned
                     96:  *    in *cnp.  This is useful for determining how long a
                     97:  *    directory is.  If cnp is null, nothing is returned.
                     98:  */
                     99: int
                    100: pcbmap(dep, findcn, bnp, cnp)
                    101:        struct denode *dep;
                    102:        u_long findcn;          /* file relative cluster to get         */
                    103:        daddr_t *bnp;           /* returned filesys relative blk number */
                    104:        u_long *cnp;            /* returned cluster number              */
                    105: {
                    106:        int error;
                    107:        u_long i;
                    108:        u_long cn;
                    109:        u_long prevcn;
                    110:        u_long byteoffset;
                    111:        u_long bn;
                    112:        u_long bo;
                    113:        struct buf *bp = NULL;
                    114:        u_long bp_bn = -1;
                    115:        struct pcfsmount *pmp = dep->de_pmp;
                    116:        u_long bsize;
                    117:        int fat12 = FAT12(pmp); /* 12 bit fat   */
                    118: 
                    119:        fc_bmapcalls++;
                    120: 
                    121: /*
                    122:  *  If they don't give us someplace to return a value
                    123:  *  then don't bother doing anything.
                    124:  */
                    125:        if (bnp == NULL  &&  cnp == NULL)
                    126:                return 0;
                    127: 
                    128:        cn = dep->de_StartCluster;
                    129: /*
                    130:  *  The "file" that makes up the root directory is contiguous,
                    131:  *  permanently allocated, of fixed size, and is not made up
                    132:  *  of clusters.  If the cluster number is beyond the end of
                    133:  *  the root directory, then return the number of clusters in
                    134:  *  the file.
                    135:  */
                    136:        if (cn == PCFSROOT) {
                    137:                if (dep->de_Attributes & ATTR_DIRECTORY) {
                    138:                        if (findcn * pmp->pm_SectPerClust > pmp->pm_rootdirsize) {
                    139:                                if (cnp)
                    140:                                        *cnp = pmp->pm_rootdirsize / pmp->pm_SectPerClust;
                    141:                                return E2BIG;
                    142:                        }
                    143:                        if (bnp)
                    144:                                *bnp = pmp->pm_rootdirblk + (findcn * pmp->pm_SectPerClust);
                    145:                        if (cnp)
                    146:                                *cnp = PCFSROOT;
                    147:                        return 0;
                    148:                }
                    149:                else {  /* just an empty file */
                    150:                        if (cnp)
                    151:                                *cnp = 0;
                    152:                        return E2BIG;
                    153:                }
                    154:        }
                    155: 
                    156: /*
                    157:  *  Rummage around in the fat cache, maybe we can avoid
                    158:  *  tromping thru every fat entry for the file.
                    159:  *  And, keep track of how far off the cache was from
                    160:  *  where we wanted to be.
                    161:  */
                    162:        i = 0;
                    163:        fc_lookup(dep, findcn, &i, &cn);
                    164:        if ((bn = findcn - i) >= LMMAX)
                    165:                fc_largedistance++;
                    166:        else
                    167:                fc_lmdistance[bn]++;
                    168: 
                    169: /*
                    170:  *  Handle all other files or directories the normal way.
                    171:  */
                    172:        for (; i < findcn; i++) {
                    173:                if (PCFSEOF(cn))
                    174:                        goto hiteof;
                    175:                byteoffset = FATOFS(pmp, cn);
                    176:                fatblock(pmp, byteoffset, &bn, &bsize, &bo);
                    177:                if (bn != bp_bn) {
                    178:                        if (bp)
                    179:                                brelse(bp);
                    180:                        error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
                    181:                        if (error) {
                    182:                                brelse(bp);
                    183:                                return error;
                    184:                        }
                    185:                        bp_bn = bn;
                    186:                }
                    187:                prevcn = cn;
                    188:                cn = getushort(&bp->b_un.b_addr[bo]);
                    189:                if (fat12) {
                    190:                        if (prevcn & 1)
                    191:                                cn >>= 4;
                    192:                        cn &= 0x0fff;
                    193: /*
                    194:  *  Force the special cluster numbers in the range
                    195:  *  0x0ff0-0x0fff to be the same as for 16 bit cluster
                    196:  *  numbers to let the rest of pcfs think it is always
                    197:  *  dealing with 16 bit fats.
                    198:  */
                    199:                        if ((cn & 0x0ff0) == 0x0ff0)
                    200:                                cn |= 0xf000;
                    201:                }
                    202:        }
                    203: 
                    204:        if (!PCFSEOF(cn)) {
                    205:                if (bp)
                    206:                        brelse(bp);
                    207:                if (bnp)
                    208:                        *bnp = cntobn(pmp, cn);
                    209:                if (cnp)
                    210:                        *cnp = cn;
                    211:                fc_setcache(dep, FC_LASTMAP, i, cn);
                    212:                return 0;
                    213:        }
                    214: 
                    215: hiteof:;
                    216:        if (cnp)
                    217:                *cnp = i;
                    218:        if (bp)
                    219:                brelse(bp);
                    220:        /* update last file cluster entry in the fat cache */
                    221:        fc_setcache(dep, FC_LASTFC, i-1, prevcn);
                    222:        return E2BIG;
                    223: }
                    224: 
                    225: /*
                    226:  *  Find the closest entry in the fat cache to the
                    227:  *  cluster we are looking for.
                    228:  */
                    229: fc_lookup(dep, findcn, frcnp, fsrcnp)
                    230:        struct denode *dep;
                    231:        u_long findcn;
                    232:        u_long *frcnp;
                    233:        u_long *fsrcnp;
                    234: {
                    235:        int i;
                    236:        u_long cn;
                    237:        struct fatcache *closest = 0;
                    238: 
                    239:        for (i = 0; i < FC_SIZE; i++) {
                    240:                cn = dep->de_fc[i].fc_frcn;
                    241:                if (cn != FCE_EMPTY  &&  cn <= findcn) {
                    242:                        if (closest == 0  ||  cn > closest->fc_frcn)
                    243:                                closest = &dep->de_fc[i];
                    244:                }
                    245:        }
                    246:        if (closest) {
                    247:                *frcnp  = closest->fc_frcn;
                    248:                *fsrcnp = closest->fc_fsrcn;
                    249:        }
                    250: }
                    251: 
                    252: /*
                    253:  *  Purge the fat cache in denode dep of all entries
                    254:  *  relating to file relative cluster frcn and beyond.
                    255:  */
                    256: fc_purge(dep, frcn)
                    257:        struct denode *dep;
                    258:        u_int frcn;
                    259: {
                    260:        int i;
                    261:        struct fatcache *fcp;
                    262: 
                    263:        fcp = dep->de_fc;
                    264:        for (i = 0; i < FC_SIZE; i++, fcp++) {
                    265:                if (fcp->fc_frcn != FCE_EMPTY  &&  fcp->fc_frcn >= frcn)
                    266:                        fcp->fc_frcn = FCE_EMPTY;
                    267:        }
                    268: }
                    269: 
                    270: /*
                    271:  *  Once the first fat is updated the other copies of
                    272:  *  the fat must also be updated.  This function does
                    273:  *  this.
                    274:  *  pmp - pcfsmount structure for filesystem to update
                    275:  *  bp - addr of modified fat block
                    276:  *  fatbn - block number relative to begin of filesystem
                    277:  *    of the modified fat block.
                    278:  */
                    279: void
                    280: updateotherfats(pmp, bp, fatbn)
                    281:        struct pcfsmount *pmp;
                    282:        struct buf *bp;
                    283:        u_long fatbn;
                    284: {
                    285:        int i;
                    286:        struct buf *bpn;
                    287: 
                    288: #if defined(PCFSDEBUG)
                    289: printf("updateotherfats(pmp %08x, bp %08x, fatbn %d)\n",
                    290:        pmp, bp, fatbn);
                    291: #endif /* defined(PCFSDEBUG) */
                    292: 
                    293: /*
                    294:  *  Now copy the block(s) of the modified fat to the other
                    295:  *  copies of the fat and write them out.  This is faster
                    296:  *  than reading in the other fats and then writing them
                    297:  *  back out.  This could tie up the fat for quite a while.
                    298:  *  Preventing others from accessing it.  To prevent us
                    299:  *  from going after the fat quite so much we use delayed
                    300:  *  writes, unless they specfied "synchronous" when the
                    301:  *  filesystem was mounted.  If synch is asked for then
                    302:  *  use bwrite()'s and really slow things down.
                    303:  */
                    304:        for (i = 1; i < pmp->pm_FATs; i++) {
                    305:                fatbn += pmp->pm_FATsecs;
                    306:                /* getblk() never fails */
                    307:                bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount);
                    308:                bcopy(bp->b_un.b_addr, bpn->b_un.b_addr,
                    309:                        bp->b_bcount);
                    310:                if (pmp->pm_waitonfat)
                    311:                        bwrite(bpn);
                    312:                else
                    313:                        bdwrite(bpn);
                    314:        }
                    315: }
                    316: 
                    317: /*
                    318:  *  Updating entries in 12 bit fats is a pain in the butt.
                    319:  *
                    320:  *  The following picture shows where nibbles go when
                    321:  *  moving from a 12 bit cluster number into the appropriate
                    322:  *  bytes in the FAT.
                    323:  *
                    324:  *      byte m        byte m+1      byte m+2
                    325:  *    +----+----+   +----+----+   +----+----+
                    326:  *    |  0    1 |   |  2    3 |   |  4    5 |   FAT bytes
                    327:  *    +----+----+   +----+----+   +----+----+
                    328:  *
                    329:  *       +----+----+----+ +----+----+----+
                    330:  *       |  3    0    1 | |  4    5    2 |
                    331:  *       +----+----+----+ +----+----+----+
                    332:  *         cluster n        cluster n+1
                    333:  *
                    334:  *    Where n is even.
                    335:  *    m = n + (n >> 2)
                    336:  *
                    337:  *     (Function no longer used)
                    338:  */
                    339: 
                    340: 
                    341: extern inline void
                    342: usemap_alloc (struct pcfsmount *pmp, u_long cn)
                    343: {
                    344:        pmp->pm_inusemap[cn / 8] |= 1 << (cn % 8);
                    345:        pmp->pm_freeclustercount--;
                    346:        /* This assumes that the lowest available cluster was allocated */
                    347:        pmp->pm_lookhere = cn + 1;
                    348: }
                    349: 
                    350: extern inline void
                    351: usemap_free (struct pcfsmount *pmp, u_long cn)
                    352: {
                    353:        pmp->pm_freeclustercount++;
                    354:        pmp->pm_inusemap[cn / 8] &= ~(1 << (cn % 8));
                    355:        if (pmp->pm_lookhere > cn)
                    356:                pmp->pm_lookhere = cn;
                    357: }
                    358: 
                    359: int
                    360: clusterfree(pmp, cluster, oldcnp)
                    361:        struct pcfsmount *pmp;
                    362:        u_long cluster;
                    363:        u_long *oldcnp;
                    364: {
                    365:        int error;
                    366:        u_long oldcn;
                    367: 
                    368:        error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, PCFSFREE);
                    369:        if (error == 0) {
                    370: /*
                    371:  *  If the cluster was successfully marked free, then update the count of
                    372:  *  free clusters, and turn off the "allocated" bit in the
                    373:  *  "in use" cluster bit map.
                    374:  */
                    375:                usemap_free(pmp, cluster);
                    376:                if (oldcnp)
                    377:                        *oldcnp = oldcn;
                    378:        }
                    379:        return error;
                    380: }
                    381: 
                    382: /*
                    383:  *  Get or Set or 'Get and Set' the cluster'th entry in the
                    384:  *  fat.
                    385:  *  function - whether to get or set a fat entry
                    386:  *  pmp - address of the pcfsmount structure for the
                    387:  *    filesystem whose fat is to be manipulated.
                    388:  *  cluster - which cluster is of interest
                    389:  *  oldcontents - address of a word that is to receive
                    390:  *    the contents of the cluster'th entry if this is
                    391:  *    a get function
                    392:  *  newcontents - the new value to be written into the
                    393:  *    cluster'th element of the fat if this is a set
                    394:  *    function.
                    395:  *
                    396:  *  This function can also be used to free a cluster
                    397:  *  by setting the fat entry for a cluster to 0.
                    398:  *
                    399:  *  All copies of the fat are updated if this is a set
                    400:  *  function.
                    401:  *  NOTE:
                    402:  *    If fatentry() marks a cluster as free it does not
                    403:  *    update the inusemap in the pcfsmount structure.
                    404:  *    This is left to the caller.
                    405:  */
                    406: int
                    407: fatentry(function, pmp, cn, oldcontents, newcontents)
                    408:        int function;
                    409:        struct pcfsmount *pmp;
                    410:        u_long cn;
                    411:        u_long *oldcontents;
                    412:        u_long newcontents;
                    413: {
                    414:        int error;
                    415:        u_long readcn;
                    416:        u_long bn, bo, bsize, byteoffset;
                    417:        struct buf *bp;
                    418: /*printf("fatentry(func %d, pmp %08x, clust %d, oldcon %08x, newcon %d)\n",
                    419:        function, pmp, cluster, oldcontents, newcontents);*/
                    420: 
                    421: #ifdef DIAGNOSTIC
                    422: /*
                    423:  *  Be sure they asked us to do something.
                    424:  */
                    425:        if ((function & (FAT_SET | FAT_GET)) == 0) {
                    426:                printf("fatentry(): function code doesn't specify get or set\n");
                    427:                return EINVAL;
                    428:        }
                    429: 
                    430: /*
                    431:  *  If they asked us to return a cluster number
                    432:  *  but didn't tell us where to put it, give them
                    433:  *  an error.
                    434:  */
                    435:        if ((function & FAT_GET)  &&  oldcontents == NULL) {
                    436:                printf("fatentry(): get function with no place to put result\n");
                    437:                return EINVAL;
                    438:        }
                    439: #endif
                    440: 
                    441: /*
                    442:  *  Be sure the requested cluster is in the filesystem.
                    443:  */
                    444:        if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster)
                    445:                return EINVAL;
                    446: 
                    447:        byteoffset = FATOFS(pmp, cn);
                    448:        fatblock(pmp, byteoffset, &bn, &bsize, &bo);
                    449:        error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
                    450:        if (error) {
                    451:                brelse(bp);
                    452:                return error;
                    453:        }
                    454:        if (function & FAT_GET) {
                    455:                readcn = getushort(&bp->b_un.b_addr[bo]);
                    456:                if (FAT12(pmp)) {
                    457:                        if (cn & 1)
                    458:                                readcn >>= 4;
                    459:                        readcn &= 0x0fff;
                    460:                        /* map certain 12 bit fat entries to 16 bit */
                    461:                        if ((readcn & 0x0ff0) == 0x0ff0)
                    462:                                readcn |= 0xf000;
                    463:                }
                    464:                *oldcontents = readcn;
                    465:        }
                    466:        if (function & FAT_SET) {
                    467:                if (FAT12(pmp)) {
                    468:                        readcn = getushort(&bp->b_un.b_addr[bo]);
                    469:                        if (cn & 1) {
                    470:                                readcn &= 0x000f;
                    471:                                readcn |= (newcontents << 4);
                    472:                        }
                    473:                        else {
                    474:                                readcn &= 0xf000;
                    475:                                readcn |= (newcontents << 0);
                    476:                        }
                    477:                        putushort(&bp->b_un.b_addr[bo], readcn);
                    478:                }
                    479:                else
                    480:                        putushort(&bp->b_un.b_addr[bo], newcontents);
                    481:                updateotherfats(pmp, bp, bn);
                    482: /*
                    483:  *  Write out the first fat last.
                    484:  */
                    485:                if (pmp->pm_waitonfat)
                    486:                        bwrite(bp);
                    487:                else
                    488:                        bdwrite(bp);
                    489:                bp = NULL;
                    490:                pmp->pm_fmod++;
                    491:        }
                    492:        if (bp)
                    493:                brelse(bp);
                    494:        return 0;
                    495: }
                    496: 
                    497: /*
                    498:  *  Allocate a free cluster.
                    499:  *  pmp - 
                    500:  *  retcluster - put the allocated cluster's number here.
                    501:  *  fillwith - put this value into the fat entry for the
                    502:  *     allocated cluster.
                    503:  */
                    504: int
                    505: clusteralloc(pmp, retcluster, fillwith)
                    506:        struct pcfsmount *pmp;
                    507:        u_long *retcluster;
                    508:        u_long fillwith;
                    509: {
                    510:        int error;
                    511:        u_long cn;
                    512:        u_long idx, max_idx, bit, map;
                    513: 
                    514:        max_idx = pmp->pm_maxcluster / 8;
                    515:        for (idx = pmp->pm_lookhere / 8; idx <= max_idx; idx++) {
                    516:                map = pmp->pm_inusemap[idx];
                    517:                if (map != 0xff) {
                    518:                        for (bit = 0; bit < 8; bit++) {
                    519:                                if ((map & (1 << bit)) == 0) {
                    520:                                        cn = idx * 8 + bit;
                    521:                                        goto found_one;
                    522:                                }
                    523:                        }
                    524:                }
                    525:        }
                    526:        return ENOSPC;
                    527: 
                    528: found_one:;
                    529:        error = fatentry(FAT_SET, pmp, cn, 0, fillwith);
                    530:        if (error == 0) {
                    531:                usemap_alloc(pmp, cn);
                    532:                *retcluster = cn;
                    533:        }
                    534: #if defined(PCFSDEBUG)
                    535: printf("clusteralloc(): allocated cluster %d\n", cn);
                    536: #endif /* defined(PCFSDEBUG) */
                    537:        return error;
                    538: }
                    539: 
                    540: /*
                    541:  *  Free a chain of clusters.
                    542:  *  pmp - address of the pcfs mount structure for the
                    543:  *    filesystem containing the cluster chain to be freed.
                    544:  *  startcluster - number of the 1st cluster in the chain
                    545:  *    of clusters to be freed.
                    546:  */
                    547: int
                    548: freeclusterchain(pmp, startcluster)
                    549:        struct pcfsmount *pmp;
                    550:        u_long startcluster;
                    551: {
                    552:        u_long nextcluster;
                    553:        int error = 0;
                    554: 
                    555:        while (startcluster >= CLUST_FIRST  &&  startcluster <= pmp->pm_maxcluster) {
                    556:                error = clusterfree(pmp, startcluster, &nextcluster);
                    557:                if (error) {
                    558:                        printf("freeclusterchain(): free failed, cluster %d\n",
                    559:                                startcluster);
                    560:                        break;
                    561:                }
                    562:                startcluster = nextcluster;
                    563:        }
                    564:        return error;
                    565: }
                    566: 
                    567: /*
                    568:  *  Read in fat blocks looking for free clusters.
                    569:  *  For every free cluster found turn off its
                    570:  *  corresponding bit in the pm_inusemap.
                    571:  */
                    572: int
                    573: fillinusemap(pmp)
                    574:        struct pcfsmount *pmp;
                    575: {
                    576:        struct buf *bp = NULL;
                    577:        u_long cn, readcn;
                    578:        int error;
                    579:        int fat12 = FAT12(pmp);
                    580:        u_long bn, bo, bsize, byteoffset;
                    581: 
                    582: /*
                    583:  *  Mark all clusters in use, we mark the free ones in the
                    584:  *  fat scan loop further down.
                    585:  */
                    586:        for (cn = 0; cn < (pmp->pm_maxcluster >> 3) + 1; cn++)
                    587:                pmp->pm_inusemap[cn] = 0xff;
                    588: 
                    589: /*
                    590:  *  Figure how many free clusters are in the filesystem
                    591:  *  by ripping thougth the fat counting the number of
                    592:  *  entries whose content is zero.  These represent free
                    593:  *  clusters.
                    594:  */
                    595:        pmp->pm_freeclustercount = 0;
                    596:        pmp->pm_lookhere = pmp->pm_maxcluster + 1;
                    597:        for (cn = CLUST_FIRST; cn <= pmp->pm_maxcluster; cn++) {
                    598:                byteoffset = FATOFS(pmp, cn);
                    599:                bo = byteoffset % pmp->pm_fatblocksize;
                    600:                if (!bo || !bp) {
                    601:                        /* Read new FAT block */
                    602:                        if (bp)
                    603:                                brelse(bp);
                    604:                        fatblock(pmp, byteoffset, &bn, &bsize, NULL);
                    605:                        error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
                    606:                        if (error) {
                    607:                                brelse(bp);
                    608:                                return error;
                    609:                        }
                    610:                }
                    611:                readcn = getushort(&bp->b_un.b_addr[bo]);
                    612:                if (fat12) {
                    613:                        if (cn & 1)
                    614:                                readcn >>= 4;
                    615:                        readcn &= 0x0fff;
                    616:                }
                    617:                
                    618:                if (readcn == 0)
                    619:                        usemap_free(pmp, cn);
                    620:        }
                    621:        brelse(bp);
                    622:        return 0;
                    623: }
                    624: 
                    625: /*
                    626:  *  Allocate a new cluster and chain it onto the end of the
                    627:  *  file.
                    628:  *  dep - the file to extend
                    629:  *  bpp - where to return the address of the buf header for the
                    630:  *        new file block
                    631:  *  ncp - where to put cluster number of the newly allocated file block
                    632:  *        If this pointer is 0, do not return the cluster number.
                    633:  *
                    634:  *  NOTE:
                    635:  *   This function is not responsible for turning on the DEUPD
                    636:  *   bit if the de_flag field of the denode and it does not
                    637:  *   change the de_FileSize field.  This is left for the caller
                    638:  *   to do.
                    639:  */
                    640: int
                    641: extendfile(dep, bpp, ncp)
                    642:        struct denode *dep;
                    643:        struct buf **bpp;
                    644:        u_int *ncp;
                    645: {
                    646:        int error = 0;
                    647:        u_long frcn;
                    648:        u_long cn;
                    649:        struct pcfsmount *pmp = dep->de_pmp;
                    650: 
                    651: /*
                    652:  *  Don't try to extend the root directory
                    653:  */
                    654:        if (DETOV(dep)->v_flag & VROOT) {
                    655:                printf("extendfile(): attempt to extend root directory\n");
                    656:                return ENOSPC;
                    657:        }
                    658: 
                    659: /*
                    660:  *  If the "file's last cluster" cache entry is empty,
                    661:  *  and the file is not empty,
                    662:  *  then fill the cache entry by calling pcbmap().
                    663:  */
                    664:        fc_fileextends++;
                    665:        if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY  &&
                    666:            dep->de_StartCluster != 0) {
                    667:                fc_lfcempty++;
                    668:                error = pcbmap(dep, 0xffff, 0, &cn);
                    669:                /* we expect it to return E2BIG */
                    670:                if (error != E2BIG)
                    671:                        return error;
                    672:                error = 0;
                    673:        }
                    674: 
                    675: /*
                    676:  *  Allocate another cluster and chain onto the end of the file.
                    677:  *  If the file is empty we make de_StartCluster point to the
                    678:  *  new block.  Note that de_StartCluster being 0 is sufficient
                    679:  *  to be sure the file is empty since we exclude attempts to
                    680:  *  extend the root directory above, and the root dir is the
                    681:  *  only file with a startcluster of 0 that has blocks allocated
                    682:  *  (sort of).
                    683:  */
                    684:        if (error = clusteralloc(pmp, &cn, CLUST_EOFE))
                    685:                return error;
                    686:        if (dep->de_StartCluster == 0) {
                    687:                dep->de_StartCluster = cn;
                    688:                frcn = 0;
                    689:        } else {
                    690:                error = fatentry(FAT_SET, pmp, dep->de_fc[FC_LASTFC].fc_fsrcn,
                    691:                        0, cn);
                    692:                if (error) {
                    693:                        clusterfree(pmp, cn, NULL);
                    694:                        return error;
                    695:                }
                    696: 
                    697:                frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
                    698:        }
                    699: 
                    700: /*
                    701:  *  Update the "last cluster of the file" entry in the denode's
                    702:  *  fat cache.
                    703:  */
                    704:        fc_setcache(dep, FC_LASTFC, frcn, cn);
                    705: 
                    706: /*
                    707:  *  Get the buf header for the new block of the file.
                    708:  */
                    709:        if (dep->de_Attributes & ATTR_DIRECTORY)
                    710:                *bpp = getblk(pmp->pm_devvp, cntobn(pmp, cn),
                    711:                        pmp->pm_bpcluster);
                    712:        else
                    713:                *bpp = getblk(DETOV(dep), frcn, pmp->pm_bpcluster);
                    714:        clrbuf(*bpp);
                    715: 
                    716:        if (dep->de_Attributes & ATTR_DIRECTORY)
                    717:                /* If we extend a directory, me must record the new size */
                    718:                dep->de_FileSize = (frcn + 1) * pmp->pm_bpcluster;
                    719: 
                    720: /*
                    721:  *  Give them the filesystem relative cluster number
                    722:  *  if they want it.
                    723:  */
                    724:        if (ncp)
                    725:                *ncp = cn;
                    726:        return 0;
                    727: }

unix.superglobalmegacorp.com

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