Annotation of 42BSD/ingres/source/dbu/nmodify.c, revision 1.1.1.1

1.1       root        1: # include      <pv.h>
                      2: # include      <ingres.h>
                      3: # include      <aux.h>
                      4: # include      <access.h>
                      5: # include      <batch.h>
                      6: # include      <lock.h>
                      7: # include      <fileio.h>
                      8: # include      <opsys.h>
                      9: # include      <func.h>
                     10: # include      <sccs.h>
                     11: 
                     12: SCCSID(@(#)nmodify.c   7.2     6/4/83)
                     13: 
                     14: extern short   tTdbu[];
                     15: extern int     modify();
                     16: extern         int     null_fn();
                     17: 
                     18: struct fn_def ModifyFn =
                     19: {
                     20:        "MODIFY",
                     21:        modify,
                     22:        null_fn,
                     23:        null_fn,
                     24:        NULL,
                     25:        0,
                     26:        tTdbu,
                     27:        100,
                     28:        'Z',
                     29:        0
                     30: };
                     31: 
                     32: /*
                     33: **  MODIFY -- converts any relation to the specified
                     34: **             storage structure
                     35: **
                     36: **     arguments:
                     37: **     0 - relation name
                     38: **     1 - storage structure ("heap", "cheap", "hash", "chash",
                     39: **             "isam", "cisam", "btree")
                     40: **     2 - "name" for attribute names, or "num" for numbers
                     41: **     3 - key1
                     42: **     4 - key2
                     43: **         .
                     44: **         .
                     45: **     i - null
                     46: **     i+1 - option name (e.g., "fillfactor")
                     47: **     i+2 - option value
                     48: **         .
                     49: **         .
                     50: **
                     51: **     If all the options default, parameter i -> pc are omitted.
                     52: **     If no keys are provided, parameter 2 is omitted.
                     53: **
                     54: **     History:
                     55: **             12/28/78 (rse) -- added descending sort option
                     56: **             9/12/78 -- (marc) modified to give error message
                     57: **                     5519 when someone tries to modify a view.
                     58: **                     For this I split the openr mode 0 into 2,
                     59: **                     mode -1 then -2.
                     60: **             9/25/78 -- (marc) 2 openr's replaced by one
                     61: **                     as view error code put in openr
                     62: **
                     63: */
                     64: 
                     65: int            F_fac, Mn_pages, Mx_pages;
                     66: 
                     67: struct modtab
                     68: {
                     69:        char    *type;
                     70:        char    newrelspec;
                     71:        char    yeskeys;
                     72:        char    sortit;
                     73:        char    yes_seq;
                     74:        int     f_fac;
                     75:        int     mn_pages;
                     76:        int     mx_pages;
                     77: };
                     78: 
                     79: 
                     80: struct modtab  Modtab[] =
                     81: {
                     82:        /* type         spec    keys    sort    seq     ffac    min     max */
                     83: 
                     84:        "heap",         M_HEAP, FALSE,  FALSE,  FALSE,  0,      0,      0,
                     85:        "cheap",        -M_HEAP,FALSE,  FALSE,  FALSE,  0,      0,      0,
                     86:        "hash",         M_HASH, TRUE,   TRUE,   FALSE,  50,     10,     -1,
                     87:        "chash",        -M_HASH,TRUE,   TRUE,   FALSE,  75,     1,      -1,
                     88:        "isam",         M_ISAM, TRUE,   TRUE,   FALSE,  80,     0,      0,
                     89:        "cisam",        -M_ISAM,TRUE,   TRUE,   FALSE,  100,    0,      0,
                     90:        "btree",        M_BTREE, TRUE,  TRUE,   FALSE,  66,     0,      0,
                     91:        "heapsort",     M_HEAP, TRUE,   TRUE,   TRUE,   0,      0,      0,
                     92:        "cheapsort",    -M_HEAP,TRUE,   TRUE,   TRUE,   0,      0,      0,
                     93:        "truncated",    M_TRUNC,FALSE,  FALSE,  FALSE,  0,      0,      0,
                     94:        0
                     95: };
                     96: 
                     97: struct mod_info
                     98: {
                     99:        char    outfile[MAXNAME + 4];   /* result file filled by ksort */
                    100:        char    formfile[MAXNAME + 4];  /* file with descriptor for ksort */
                    101:        char    infile[MAXNAME + 4];    /* input file for ksort (relation itself */
                    102:        char    reltemp[MAXNAME + 4];   /* file holding new relation */
                    103:        char    spfile[MAXNAME + 4], spflag;    /* isam spool file for overflow */
                    104: };
                    105: 
                    106: struct mod_info        Mod_info;
                    107: 
                    108: modify(pc, pv)
                    109: int    pc;
                    110: PARM   *pv;
                    111: {
                    112:        register int            i;
                    113:        register char           *rname;
                    114:        register struct modtab  *mp;
                    115:        int                     sorted;
                    116:        DESC                    dold, dnew;
                    117:        long                    temptid;
                    118:        extern int              Noupdt;
                    119: 
                    120:        
                    121: #      ifdef xZTR1
                    122:        if (tTf(34, -1))
                    123:        {
                    124:                printf("enter modify\n");
                    125:                prvect(pc, pv);
                    126:        }
                    127: #      endif
                    128: 
                    129:        pv[pc].pv_val.pv_str = NULL;
                    130: 
                    131:        /* check for nice parameters */
                    132:        if (pc < 2)
                    133:                syserr("MODIFY: pc %d", pc);
                    134: 
                    135:        /* save relation name for error messages */
                    136:        rname = (pv++)->pv_val.pv_str;  /* *pv now pointes to storage spec */
                    137: 
                    138:        /* check for good relation */
                    139:        i = openr(&dold, 0, rname);
                    140:        if (i == AMOPNVIEW_ERR)
                    141:                return (error(5519, rname, 0));
                    142:        if (i > 0)
                    143:                /* reln does not exist */
                    144:                return (error(5500, rname, 0)); 
                    145:        else if (i < 0)
                    146:                syserr("MODIFY: openr (%.14s) %d", rname, i);
                    147:        /* can only modify a relation you own and isn't a sys rel */
                    148:        
                    149:        if (!bequal(Usercode, dold.reldum.relowner, 2))
                    150:        {
                    151:                i = 5501;
                    152:        }
                    153:        if ((dold.reldum.relstat & S_CATALOG) && Noupdt)
                    154:        {
                    155:                i = 5504;
                    156:        }
                    157:        if (i)
                    158:        {
                    159:                closer(&dold);
                    160:                return (error(i, rname, 0));
                    161:        }
                    162: 
                    163:        /*
                    164:        ** Form descriptor for new relation. Here we need to
                    165:        ** separate the pages from the old and new relations.
                    166:        ** Since pages are identified by the TID of the relation
                    167:        ** relation tuple, both old and new have the same identifiers.
                    168:        ** To avoid this problem, a special TID is hand crafted for
                    169:        ** the new relation.
                    170:        */
                    171:        bmove(&dold, &dnew, sizeof dnew);
                    172:        dnew.reltid.line_id = (char) -2;        /* choose impossible reltid */
                    173: 
                    174:        /* In case of an interrupt from a previous modify,
                    175:        ** there might be pages around. Get rid of them.
                    176:        */
                    177:        cleanrel(&dnew);
                    178: 
                    179:        ingresname(dold.reldum.relid, dold.reldum.relowner, Mod_info.infile);
                    180: 
                    181:        /* scan for entry in relspec table */
                    182:        for (mp = Modtab; mp->type; mp++)
                    183:                if (sequal(mp->type, pv->pv_val.pv_str))
                    184:                        break;
                    185: 
                    186:        /* if not found, error */
                    187:        if (!mp->type)
                    188:        {
                    189:                closer(&dold);
                    190:                return (error(5510, rname, pv->pv_val.pv_str, 0));      /* bad relspec */
                    191:        }
                    192:        dnew.reldum.relspec = mp->newrelspec;
                    193: 
                    194:        if (dnew.reldum.relspec == M_TRUNC)
                    195:                dnew.reldum.relspec = M_HEAP;
                    196: 
                    197:        pv++;   /* now points to first parameter */
                    198: 
                    199:        F_fac = mp->f_fac;
                    200:        Mn_pages = mp->mn_pages;
                    201:        Mx_pages = mp->mx_pages;
                    202: 
                    203:        /* get the key domains information */
                    204:        if (i = getkeys(&pv, rname, &dnew, mp))
                    205:        {
                    206:                closer(&dold);
                    207:                return (i);     /* user error */
                    208:        }
                    209: 
                    210:        /* get fillfactor and other options if any */
                    211:        if (i = getfill(pv, rname, mp))
                    212:        {
                    213:                closer(&dold);
                    214:                return (i);     /* user error */
                    215:        }
                    216: 
                    217: 
                    218:        /* lock the relation relation */
                    219:        if (Lockrel)
                    220:        {
                    221:                get_p_tid(&dold, &temptid);
                    222:                setrll(A_SLP, temptid, M_EXCL);
                    223:        }
                    224: 
                    225:        /* compute new relation parameters & build descriptor */
                    226:        make_newrel(&dnew);
                    227: 
                    228:        if (sorted = (mp->sortit && (dold.reldum.reltups != 0)))
                    229:                sortrel(&dold, &dnew);
                    230: 
                    231:        /* physically create the new relation */
                    232:        if (formatpg(&dnew, (dnew.reldum.relspec == M_BTREE) ? dnew.reldum.relprim + 1 : dnew.reldum.relprim) != 0)
                    233:                syserr("modify: formatpg");
                    234: 
                    235:        /* clear relgiven field; if heap remove any keys */
                    236:        clearkeys(&dnew);
                    237:        if (abs(dnew.reldum.relspec) == M_HEAP)
                    238:                for (i = 1; i <= dnew.reldum.relatts; i++)
                    239:                        dnew.relxtra[i] = 0;
                    240: 
                    241:        if (mp->newrelspec != M_TRUNC)
                    242:                fill_rel(&dold, &dnew, sorted);
                    243: 
                    244:        closer(&dold);  /* error return is impossible */
                    245:        if (abs(dnew.reldum.relspec) == M_ISAM)
                    246:        {
                    247:                if (i = bldindex(&dnew))
                    248:                        syserr("bldindex: %.14s %d", dnew.reldum.relid, i);
                    249:                unspool(&dnew);
                    250:        }
                    251:        else if (dnew.reldum.relspec == M_BTREE)
                    252:        {
                    253:                if (i = bldbindex(&dnew))
                    254:                        syserr("bldbindex: %.14s %d", dnew.reldum.relid, i);
                    255:        }
                    256: 
                    257:        /*
                    258:        ** New relation is now complete. The system relations need to
                    259:        ** be updated. First destroy all buffers with pages from the
                    260:        ** new relation.
                    261:        */
                    262:        if (i = cleanrel(&dnew))
                    263:                syserr("modify:clean new %d,%.14s", i, dnew.reldum.relid);
                    264: 
                    265:        fill_batch(&dold, &dnew);
                    266: 
                    267:        /*
                    268:        ** Close the file for the new relation. This must be
                    269:        ** done after the fill_batch in case we are modifing
                    270:        ** the attribute relation.
                    271:        */
                    272:        close(dnew.relfp);
                    273:        dnew.relopn = 0;
                    274:        ruboff("modify");
                    275:        modupdate();
                    276:        rubon();
                    277: 
                    278:        if (Lockrel)
                    279:                unlrl(temptid);
                    280: 
                    281: #      ifdef xZTM
                    282:        if (tTf(35, 1))
                    283:                timtrace(16, 0);
                    284: #      endif
                    285:        return (0);
                    286: }
                    287: 
                    288: 
                    289: getkeys(ppv, relname, desc, mp)
                    290: PARM           **ppv;
                    291: char           *relname;
                    292: DESC           *desc;
                    293: struct modtab  *mp;
                    294: {
                    295:        register PARM           *pv;
                    296:        register char           *cp;
                    297:        register DESC           *d;
                    298:        int                     namemode, sort_only, as_ds;
                    299:        int                     i, keyno, keywid;
                    300:        struct attribute        attkey, atttup;
                    301:        TID                     tid;
                    302:        extern DESC             Attdes;
                    303: 
                    304:        pv = *ppv;      /* copy list of params */
                    305: 
                    306:        d = desc;
                    307: 
                    308:        /* zero key info */
                    309:        for (i = 0; i <= d->reldum.relatts; i++)
                    310:                d->relxtra[i] = d->relgiven[i] = 0;
                    311: 
                    312:        /* determine whether there are any keys at all */
                    313:        keyno = 0;
                    314:        keywid = 0;
                    315:        sort_only = FALSE;
                    316:        cp = pv->pv_val.pv_str;
                    317: 
                    318:        if (cp == NULL || *cp == NULL)
                    319:        {
                    320:                /* no key information. default as needed */
                    321:                if (mp->yeskeys)
                    322:                {
                    323:                        cp = "\1";      /* default to first key */
                    324:                        namemode = FALSE;
                    325:                }
                    326:                else
                    327:                        pv++;   /* point one to far */
                    328:        }
                    329:        else
                    330:        {
                    331:                /* check for name mode */
                    332:                if (namemode = sequal(cp, "name"))
                    333:                {
                    334: 
                    335:                        /* check attribute names, and convert them to numbers */
                    336:                        opencatalog("attribute", 0);
                    337:                        setkey(&Attdes, &attkey, Mod_info.infile, ATTRELID);
                    338:                        setkey(&Attdes, &attkey, Usercode, ATTOWNER);
                    339:                }
                    340:                pv++;   /* inc to next key */
                    341:                cp = (pv++)->pv_val.pv_str;
                    342:        }
                    343: 
                    344: 
                    345:        /* scan for attribute names */
                    346:        for (; cp != NULL; cp = (pv++)->pv_val.pv_str)
                    347:        {
                    348:                /* check for separator between keys & options */
                    349:                if (*cp == NULL)
                    350:                {
                    351:                        pv++;   /* point two past NULL */
                    352:                        break;
                    353:                }
                    354: 
                    355:                if (namemode)
                    356:                {
                    357:                        /* check for "sort only" attribute */
                    358:                        if (*cp == '#')
                    359:                        {
                    360:                                cp++;   /* inc to start of name */
                    361:                                sort_only = TRUE;
                    362:                        }
                    363: 
                    364:                        /* check for ascending/descending modifier */
                    365:                        if ((as_ds = modseqkey(cp, relname, mp->yes_seq)) > 0)
                    366:                                return (as_ds); /* error */
                    367: 
                    368:                        setkey(&Attdes, &attkey, cp, ATTNAME);
                    369:                        i = getequal(&Attdes, &attkey, &atttup, &tid);
                    370:                        if (i < 0)
                    371:                                syserr("MODIFY: geteq(att) %d", i);
                    372:                        if (i > 0)
                    373:                        {
                    374:                                return (error(5511, relname, cp, 0));   /* bad att name */
                    375:                        }
                    376:                        i = atttup.attid;
                    377:                }
                    378:                else
                    379:                {
                    380:                        i = *cp;
                    381:                        as_ds = 0;
                    382:                }
                    383: 
                    384:                /* add new key to descriptor */
                    385:                keyno++;
                    386:                if (!sort_only)
                    387:                {
                    388:                        d->relxtra[i] = keyno;
                    389:                        keywid += (d->relfrml[i] & I1MASK);
                    390:                }
                    391:                if (d->relgiven[i])
                    392:                        return (error(5507, relname, cp, 0));   /* duplicate attribute */
                    393:                d->relgiven[i] = as_ds == 0 ? keyno : -keyno;
                    394:        }
                    395:        pv--;   /* back up one to point to "-1" terminator */
                    396: 
                    397: 
                    398:        if (abs(d->reldum.relspec) == M_ISAM && keywid > (MAXTUP / 2 - 4))
                    399:        {
                    400:                return (error(5508, relname, iocv(keywid), 0));
                    401:        }
                    402: 
                    403:        /* if a heap, there can be no keys */
                    404:        if (!mp->yeskeys && keyno != 0)
                    405:        {
                    406:                return (error(5502, relname, mp->type, 0));     /* no keys allowed on heap */
                    407:        }
                    408: 
                    409:        /* fill out default sort on remainder of keys */
                    410:        if (mp->yeskeys)
                    411:                for (i = 1; i <= d->reldum.relatts; i++)
                    412:                        if (d->relgiven[i] == 0)
                    413:                                d->relgiven[i] = ++keyno;
                    414:        *ppv = pv;
                    415:        return (0);
                    416: }
                    417: 
                    418: 
                    419: modseqkey(domain, relname, seq_ok)
                    420: char   *domain;
                    421: char   *relname;
                    422: int    seq_ok;
                    423: {
                    424:        register char   *cp, c;
                    425:        register int    ret;
                    426: 
                    427:        ret = 0;
                    428: 
                    429:        for (cp = domain; c = *cp++; )
                    430:                if (c == ':')
                    431:                        break;
                    432: 
                    433:        if (c != '\0')
                    434:        {
                    435:                /* replace ":" with null */
                    436:                *(cp - 1) = '\0';
                    437: 
                    438:                /* verify sequence is valid */
                    439:                if (!seq_ok)
                    440:                        ret = error(5520, relname, cp, domain, 0);
                    441:                else if (sequal("descending", cp) || sequal("d", cp))
                    442:                        ret = -1;
                    443:                else if (!(sequal("ascending", cp) || sequal("a", cp)))
                    444:                        ret = error(5518, relname, cp, domain, 0);
                    445:        }
                    446: 
                    447:        return (ret);
                    448: }
                    449: /*
                    450: **     GETFILL -- Get fill factor and minimum pages parameters
                    451: **             from argument list, convert them from ascii to integer
                    452: **             and store them in global variables.  If the global
                    453: **             variable for the corresponding parameter is zero,
                    454: **             it means that that parameter is not allowed and an
                    455: **             error is generated.
                    456: */
                    457: 
                    458: getfill(pvx, rel, mp)
                    459: PARM           *pvx;
                    460: char           *rel;
                    461: struct modinfo *mp;
                    462: {
                    463:        register PARM   *pv;
                    464:        register char   *p1;
                    465:        register int    err;
                    466:        char            *p2;
                    467:        int             fill_flag, min_flag, max_flag;
                    468: 
                    469:        pv = pvx;
                    470:        err = 0;
                    471:        fill_flag = min_flag = max_flag = FALSE;
                    472: 
                    473:        while ((p1 = (pv++)->pv_val.pv_str) != NULL)
                    474:        {
                    475:                p2 = (pv++)->pv_val.pv_str;
                    476:                if (sequal(p1, "fillfactor"))
                    477:                {
                    478:                        if (F_fac == 0 || fill_flag)
                    479:                        {
                    480:                                err = 5512;
                    481:                                break;
                    482:                        }
                    483:                        p1 = p2;
                    484:                        F_fac = atoi(p1);
                    485:                        if (F_fac > 100 || F_fac < 1)
                    486:                        {
                    487:                                err = 5513;
                    488:                                break;
                    489:                        }
                    490:                        fill_flag = TRUE;
                    491:                        continue;
                    492:                }
                    493:                if (sequal(p1, "minpages"))
                    494:                {
                    495:                        if (Mn_pages == 0 || min_flag)
                    496:                        {
                    497:                                err = 5512;
                    498:                                break;
                    499:                        }
                    500:                        p1 = p2;
                    501:                        Mn_pages = atoi(p1);
                    502:                        if (Mn_pages < 1)
                    503:                        {
                    504:                                err = 5514;
                    505:                                break;
                    506:                        }
                    507:                        if (max_flag && (Mn_pages > Mx_pages))
                    508:                        {
                    509:                                err = 5517;
                    510:                                break;
                    511:                        }
                    512:                        min_flag = TRUE;
                    513:                        continue;
                    514:                }
                    515:                if (sequal(p1, "maxpages"))
                    516:                {
                    517:                        if (Mx_pages == 0 || max_flag)
                    518:                        {
                    519:                                err = 5512;
                    520:                                break;
                    521:                        }
                    522:                        p1 = p2;
                    523:                        Mx_pages = atoi(p1);
                    524:                        if (Mx_pages < 1)
                    525:                        {
                    526:                                err = 5516;
                    527:                                break;
                    528:                        }
                    529:                        if (min_flag && (Mn_pages > Mx_pages))
                    530:                        {
                    531:                                err = 5517;
                    532:                                break;
                    533:                        }
                    534:                        max_flag = TRUE;
                    535:                        continue;
                    536:                }
                    537:                err = 5515;
                    538:                break;
                    539:        }
                    540:        if (err)
                    541:                return (error(err, rel, p1, 0));
                    542:        return (0);
                    543: }
                    544: /*
                    545: **     MAKE_NEWREL -- Create a file for the modified relation
                    546: **             and build one or more primary pages for the
                    547: **             relation based on its storage structure and the
                    548: **             number of tuples it must hold.
                    549: */
                    550: 
                    551: make_newrel(descx)
                    552: DESC   *descx;
                    553: {
                    554:        register DESC   *desc;
                    555:        register int    i, tups_p_page;
                    556: 
                    557:        desc = descx;
                    558:        concat(MODTEMP, Fileset, Mod_info.reltemp);
                    559:        close(creat(Mod_info.reltemp, FILEMODE));
                    560:        if ((desc->relfp = open(Mod_info.reltemp, 2)) < 0)
                    561:                syserr("MAKE_NEWREL: open %.14s %d", Mod_info.reltemp, desc->relfp);
                    562:        desc->relopn = (desc->relfp + 1) * -5;
                    563:        desc->reldum.relprim = 1;
                    564:        if (abs(desc->reldum.relspec) == M_HASH && F_fac > 0 && Mn_pages > 0)
                    565:        {
                    566:                /*
                    567:                ** Determine the number of primary pages. The following
                    568:                ** first determines the number of tuples/page which the
                    569:                ** relation should have in order to get the requested
                    570:                ** fillfactor. Then that number is divided into the
                    571:                ** number of tuples to get the number of primary pages.
                    572:                ** To avoid round off, it must guaranteed that the
                    573:                ** number of tuples per page must be at least 1.
                    574:                **
                    575:                ** primary_pages = #tuples / (#tuples/page * fillfactor)
                    576:                */
                    577:                tups_p_page = (((MAXTUP+2) / (desc->reldum.relwid+2)) * F_fac) / 100;
                    578:                if (tups_p_page == 0)
                    579:                        tups_p_page = 1;
                    580:                 /* we add one to simulate a ceiling function */
                    581:                desc->reldum.relprim = desc->reldum.reltups / tups_p_page + 1;
                    582:                if (desc->reldum.relprim < Mn_pages)
                    583:                        desc->reldum.relprim = Mn_pages;
                    584:                if (Mx_pages > 0 && desc->reldum.relprim > Mx_pages)
                    585:                        desc->reldum.relprim = Mx_pages;
                    586: #              ifdef xZTR1
                    587:                if (tTf(36, 0))
                    588:                        printf("using %ld prim pages\n", desc->reldum.relprim);
                    589: #              endif
                    590:        }
                    591:        desc->reldum.reltups = 0;
                    592:        return (0);
                    593: }
                    594: /*
                    595: **     SORTREL - Call KSORT to sort the given relation.  SORTREL
                    596: **             sets up the descriptor struct specifying the sort
                    597: **             keys and tells KSORT whether or not the hash key should
                    598: **             be included as a sort key.
                    599: */
                    600: 
                    601: sortrel(odesc, descx)
                    602: DESC   *odesc, *descx;
                    603: {
                    604:        extern char     *Pathname;
                    605:        register DESC   *desc;
                    606:        register int    fp, i;
                    607:        char            savespec;
                    608:        char            buf[50];
                    609: 
                    610:        desc = descx;
                    611:        concat(ISAM_SORTED, Fileset, Mod_info.outfile);
                    612:        if (close(creat(Mod_info.outfile, FILEMODE)))
                    613:                syserr("SORTREL: creat %.14s", Mod_info.outfile);
                    614:        concat(ISAM_DESC, Fileset, Mod_info.formfile);
                    615:        if ((fp = creat(Mod_info.formfile, FILEMODE)) < 0)
                    616:                syserr("SORTREL: creat %.14s %d", Mod_info.formfile, fp);
                    617:        if (abs(desc->reldum.relspec) == M_HASH)
                    618:        {
                    619:                /* sort on hash bucket first */
                    620:                desc->relgiven[0] = 1;
                    621:                for (i = 1; i <= desc->reldum.relatts; i++)
                    622:                        desc->relgiven[i]++;
                    623:        }
                    624:        savespec = desc->reldum.relspec;
                    625:        desc->reldum.relspec = odesc->reldum.relspec;
                    626: 
                    627:        if (write(fp, desc, sizeof *desc) != sizeof *desc)
                    628:                syserr("SORTREL: desc write err");
                    629:        close(fp);
                    630:        desc->reldum.relspec = savespec;
                    631: 
                    632:        i = fork();
                    633:        if (i == -1)
                    634:                syserr("SORTREL: fork");
                    635:        if (i == 0)
                    636:        {
                    637:                for (i = 3; i < NOFILE; i++)
                    638:                        close(i);
                    639:                concat(Pathname, "/bin/ksort", buf);
                    640:                execl(buf, buf, Fileset, iocv(tTf(37, -1)),
                    641:                        Mod_info.formfile, Mod_info.infile,
                    642:                        Mod_info.outfile, 0);
                    643:                syserr("SORTREL: exec %s", buf);
                    644:        }
                    645: 
                    646: # ifdef        xZTR1
                    647:        tTfp(37, 1, "SORTREL: after execl; pid = %d\n", i);
                    648: # endif
                    649: 
                    650:        if (fp = fullwait(i, "modify")) /* wait for ksort to complete */
                    651:                syserr("modify:ksort failed %d", fp);
                    652: 
                    653: # ifdef        xZTR1
                    654:        tTfp(37, 2, "SORTREL: after fullwait\n");
                    655: # endif
                    656: 
                    657:        unlink(Mod_info.formfile);
                    658:        return (0);
                    659: }
                    660: /*
                    661: **     FILL_REL -- Fill the new relation with tuples from either
                    662: **             the old relation or the output file of KSORT.
                    663: */
                    664: 
                    665: fill_rel(sdescx, descx, sortit)
                    666: DESC   *sdescx, *descx;
                    667: char   sortit;
                    668: {
                    669:        register DESC   *sdesc, *desc;
                    670:        register int    i;
                    671:        char            tup_buf[MAXTUP], last_tup[MAXTUP];
                    672:        char            junk[4], newreltype, anytups, chkdups;
                    673:        char            sortbuf[IOBUFSIZ], spoolbuf[IOBUFSIZ];
                    674:        int             need, j;
                    675:        long            lnum;
                    676:        TID             tid, stid, stidlim;
                    677:        FILE            *fp, *spfp;
                    678: 
                    679:        sdesc = sdescx;
                    680:        desc = descx;
                    681:        newreltype = abs(desc->reldum.relspec);
                    682:        if (sortit)
                    683:        {
                    684:                if ((fp = fopen(Mod_info.outfile, "read", sortbuf)) == NULL)
                    685:                        syserr("FILL_REL: fopen %.14s", Mod_info.outfile);
                    686:        }
                    687:        else
                    688:        {
                    689:                cleanrel(sdesc);        /* make sure each page is read fresh */
                    690:                find(sdesc, NOKEY, &stid, &stidlim);
                    691:        }
                    692:        if (newreltype == M_ISAM)
                    693:        {
                    694:                lnum = 0;
                    695:                stuff_page(&tid, &lnum);
                    696:                tid.line_id = 0;
                    697:                get_page(desc, &tid);
                    698:                concat(ISAM_SPOOL, Fileset, Mod_info.spfile);
                    699:                /* assume that spool file is not needed */
                    700:                spfp = NULL;
                    701:                Mod_info.spflag = FALSE;
                    702:                if (F_fac == 0)
                    703:                        F_fac = 100;
                    704:                /* setup relgiven field for kcompare later on */
                    705:                for (i = 1; i <= desc->reldum.relatts; i++)
                    706:                        desc->relgiven[i] = desc->relxtra[i];
                    707:        }
                    708:        else if (newreltype == M_BTREE)
                    709:        {
                    710:                lnum = 1;
                    711:                stuff_page(&tid, &lnum);
                    712:                tid.line_id = 0;
                    713:                get_page(desc, &tid);
                    714:                concat(ISAM_SPOOL, Fileset, Mod_info.spfile);
                    715:                /* assume that spool file is not needed */
                    716:                spfp = NULL;
                    717:                Mod_info.spflag = FALSE;
                    718:                if (F_fac == 0)
                    719:                        F_fac = 100;
                    720:                /* setup relgiven field for kcompare later on */
                    721:                for (i = 1; i <= desc->reldum.relatts; i++)
                    722:                        desc->relgiven[i] = desc->relxtra[i];
                    723:        }
                    724:        desc->reladds = 0;
                    725:        anytups = FALSE;
                    726:        chkdups = !sortit;
                    727:        for (;;)
                    728:        {
                    729:                if (sortit)
                    730:                {
                    731:                        i = fread(fp, tup_buf, desc->reldum.relwid);
                    732:                        if (i == 0)
                    733:                                break;
                    734:                        if (i != desc->reldum.relwid)
                    735:                                syserr("FILL_REL: fread A %d", i);
                    736:                        if (newreltype == M_HASH)
                    737:                                if (fread(fp, junk, 4) != 4)
                    738:                                        syserr("FILL_REL: fread B");
                    739:                }
                    740:                else
                    741:                {
                    742: #                      ifdef xZTR2
                    743:                        if (tTf(36, 1))
                    744:                        {
                    745:                                printf("FILL_REL: stid ");
                    746:                                dumptid(&stid);
                    747:                                printf("FILL_REL: stidlim ");
                    748:                                dumptid(&stidlim);
                    749:                        }
                    750: #                      endif
                    751:                        i = get(sdesc, &stid, &stidlim, tup_buf, TRUE);
                    752: #                      ifdef xZTR2
                    753:                        if (tTf(36, 1))
                    754:                        {
                    755:                                printf("FILLREL: get %d ", i);
                    756:                                printup(sdesc, tup_buf);
                    757:                        }
                    758: #                      endif
                    759:                        if (i < 0)
                    760:                                syserr("FILL_REL: get %d", i);
                    761:                        if (i == 1)
                    762:                                break;
                    763:                }
                    764:                if (newreltype != M_ISAM && newreltype != M_BTREE)
                    765:                {
                    766:                        if ((i = insert(desc, &tid, tup_buf, chkdups)) < 0)
                    767:                                syserr("FILL_REL: insert %d", i);
                    768: #                      ifdef xZTR2
                    769:                        if (tTf(36, 2))
                    770:                        {
                    771:                                printf("FILL_REL: insert ");
                    772:                                printup(desc, tup_buf);
                    773:                                printf("FILL_REL: insert ret %d at", i);
                    774:                                dumptid(&tid);
                    775:                        }
                    776: #                      endif
                    777:                        continue;
                    778:                }
                    779:                if (anytups)
                    780:                        i = kcompare(desc, tup_buf, last_tup);
                    781:                else
                    782:                {
                    783:                        anytups = TRUE;
                    784:                        i = 1;
                    785:                }
                    786:                bmove(tup_buf, last_tup, desc->reldum.relwid);
                    787:                need = canonical(desc, tup_buf);
                    788:                if (i == 0 && need > space_left(Acc_head))
                    789:                {
                    790:                        /* spool out this tuple. will go on overflow page later */
                    791:                        if (spfp == NULL)
                    792:                        {
                    793:                                if ((spfp = fopen(Mod_info.spfile, "write", spoolbuf)) == NULL)
                    794:                                        syserr("FILL_REL: fopen %.14s", Mod_info.spfile);
                    795:                                Mod_info.spflag = TRUE;
                    796:                        }
                    797:                        if (fwrite(spfp, tup_buf, desc->reldum.relwid) != desc->reldum.relwid)
                    798:                                syserr("FILL_REL: putb spool");
                    799:                        continue;
                    800:                }
                    801:                j = (100 - F_fac) * MAXTUP / 100;
                    802:                if (j < need)
                    803:                        j = need;
                    804:                if (i != 0 && j > space_left(Acc_head))
                    805:                {
                    806:                        if (i = add_prim(desc, &tid))
                    807:                                syserr("FILL_REL: force ovflo %d", i);
                    808:                }
                    809:                tid.line_id = newlino(need);
                    810:                put_tuple(&tid, Acctuple, need);
                    811:                desc->reladds++;
                    812:        }
                    813:        if (sortit)
                    814:        {
                    815:                fclose(fp);
                    816:                unlink(Mod_info.outfile);
                    817:        }
                    818:        if (newreltype == M_ISAM || newreltype == M_BTREE)
                    819:        {
                    820:                if (i = pageflush(Acc_head))
                    821:                        syserr("fill_rel:pg clean %d", i);
                    822:                if (spfp != NULL)
                    823:                        fclose(spfp);
                    824:        }
                    825:        desc->reldum.reltups = desc->reladds;
                    826:        desc->reladds = 0;
                    827:        return (0);
                    828: }
                    829: 
                    830: 
                    831: bldindex(dx)
                    832: DESC   *dx;
                    833: {
                    834:        register DESC   *d;
                    835:        register TID    *tid;
                    836:        register int    tmp;
                    837:        TID             tidx;
                    838:        struct accbuf   dirbuf;
                    839:        int             keywid, level, savespec, keyx[MAXDOM];
                    840:        int             offset, len;
                    841:        char            tuple[MAXTUP], temptup[MAXTUP], *key;
                    842:        long            pageid, start, stop, newstart, newstop;
                    843: 
                    844:        d = dx;
                    845:        tid = &tidx;
                    846:        for (tmp = 0; tmp < MAXDOM; tmp++)
                    847:                keyx[tmp] = 0;
                    848:        for (tmp = 1; tmp <= d->reldum.relatts; tmp++)
                    849:                if (d->relxtra[tmp] > 0)
                    850:                {
                    851:                        keyx[d->relxtra[tmp] - 1] = tmp;
                    852:                        keywid += d->relfrml[tmp] & I1MASK;
                    853:                }
                    854: 
                    855:        /* Determine the last page of the relation. This will
                    856:        ** only work if all pages have been written out. Fill_rel
                    857:        ** must guarantee that all pages have been written
                    858:        */
                    859:        level = 0;
                    860:        last_page(d, tid, 0);
                    861:        pluck_page(tid, &stop);
                    862:        start = 0;
                    863:        dirbuf.filedesc = d->relfp;
                    864:        dirbuf.rel_tupid = d->reltid.ltid;
                    865:        savespec = d->reldum.relspec;
                    866:        for (;;)
                    867:        {
                    868: #              ifdef xZTR2
                    869:                if (tTf(38, 7))
                    870:                        printf("isam: level %d\n", level);
                    871: #              endif
                    872:                dirbuf.ovflopg = start;
                    873:                dirbuf.mainpg = level;
                    874:                dirbuf.thispage = stop + 1;
                    875:                dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf);
                    876:                offset = dirbuf.linetab[0];
                    877:                dirbuf.bufstatus = BUF_DIRTY | BUF_DIRECT;
                    878: 
                    879:                dirbuf.nxtlino = 0;
                    880:                newstart = stop + 1;
                    881:                newstop = newstart;
                    882:                for (pageid = start; pageid <= stop; pageid++)
                    883:                {
                    884: #                      ifdef xZTR2
                    885:                        if (tTf(38, 8))
                    886:                                printf("isam:get key from %ld\n", pageid);
                    887: #                      endif
                    888:                        stuff_page(tid, &pageid);
                    889:                        tid->line_id = 0;
                    890:                        if (tmp = get(d, tid, tid, tuple, FALSE))
                    891:                        {
                    892:                                /*
                    893:                                ** If the relation is empty, then page 0 will
                    894:                                ** return AMINVL_ERR on a get(). Form a blank tuple
                    895:                                ** and use it to create a one tuple directory
                    896:                                */
                    897:                                if (pageid == 0 && tmp == AMINVL_ERR)
                    898:                                {
                    899:                                        clr_tuple(d, tuple);
                    900:                                }
                    901:                                else
                    902:                                {
                    903:                                        return (-2);
                    904:                                }
                    905:                        }
                    906: 
                    907:                        /*
                    908:                        ** If this is the first level then form the tuple
                    909:                        ** from the mainpage of the relation. Otherwise
                    910:                        ** the tuple is the first tuple of a directory page
                    911:                        ** and it is already correctly formed.
                    912:                        */
                    913:                        if (level == 0)
                    914:                        {
                    915:                                key = temptup;
                    916:                                for (tmp = 0; keyx[tmp] != 0; tmp++)
                    917:                                {
                    918:                                        len = d->relfrml[keyx[tmp]] & I1MASK;
                    919:                                        bmove(&tuple[d->reloff[keyx[tmp]]], key, len);
                    920:                                        key += len;
                    921:                                }
                    922:                                key = temptup;
                    923:                        }
                    924:                        else
                    925:                                key = tuple;
                    926: 
                    927:                        if (keywid > space_left(&dirbuf))
                    928:                        {
                    929:                                if (pageflush(&dirbuf))
                    930:                                        return (-3);
                    931:                                dirbuf.thispage++;
                    932:                                newstop = dirbuf.thispage;
                    933:                                dirbuf.ovflopg = pageid;
                    934:                                dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf);
                    935:                                offset = dirbuf.linetab[0];
                    936:                                dirbuf.bufstatus = BUF_DIRTY;
                    937:                                dirbuf.nxtlino = 0;
                    938:                        }
                    939:                        /* copy key to directory page */
                    940:                        bmove(key, (char *) &dirbuf + offset, keywid);
                    941: 
                    942:                        /* update next line number */
                    943:                        offset += keywid;
                    944:                        dirbuf.nxtlino++;
                    945:                        dirbuf.linetab[-dirbuf.nxtlino] = offset;
                    946:                }
                    947:                if (pageflush(&dirbuf))
                    948:                        return (-4);
                    949:                if (newstart == newstop)
                    950:                        break;
                    951:                d->reldum.relspec = abs(d->reldum.relspec);
                    952:                level++;
                    953:                start = newstart;
                    954:                stop = newstop;
                    955:        }
                    956:        d->reldum.relspec = savespec;
                    957:        d->reldum.relprim = newstart;
                    958:        return (0);
                    959: }
                    960: 
                    961: bldbindex(dx)
                    962: register DESC  *dx;
                    963: {
                    964:        register TID    *tid;
                    965:        register int    tmp;
                    966:        TID             tidx;
                    967:        struct accbuf   dirbuf;
                    968:        int             keywid, level, savespec, keyx[MAXDOM];
                    969:        int             offset, len;
                    970:        struct pgtuple  tuple, temptup;
                    971:        char            *key;
                    972:        long            pageid, start, stop, newstart, newstop;
                    973:        int             fill_leave;
                    974: 
                    975:        tid = &tidx;
                    976:        keywid = 0;
                    977:        for (tmp = 0; tmp < MAXDOM; tmp++)
                    978:                keyx[tmp] = 0;
                    979:        for (tmp = 1; tmp <= d->reldum.relatts; tmp++)
                    980:                if (d->relxtra[tmp] > 0)
                    981:                {
                    982:                        keyx[d->relxtra[tmp - 1]] = tmp;
                    983:                        keywid += d->relfrml[tmp] & I1MASK;
                    984:                }
                    985: 
                    986:        keywid += PGPTRSIZ;
                    987: 
                    988:        /* determine fill factor for directory pages */
                    989: 
                    990:        fill_leave = (100 - F_fac) * MAXTUP / 100;
                    991:        if (keywid > fill_leave)
                    992:                fill_leave = keywid;
                    993: 
                    994:        /* Determine the last page of the relation. This will
                    995:        ** only work if all pages have been written out. Fill_rel
                    996:        ** must guarantee that all pages have been written
                    997:        */
                    998: 
                    999:        level = 0;
                   1000:        last_page(d, tid, 0);
                   1001:        pluck_page(tid, &stop);
                   1002:        start = 1;                      /* page 0 is the root */
                   1003:        dirbuf.filedesc = d->relfp;
                   1004:        dirbuf.rel_tupid = d->reltid.ltid;
                   1005:        savespec = d->reldum.relspec;
                   1006:        for (;;)
                   1007:        {
                   1008: #              ifdef xZTR2
                   1009:                if (tTf(38, 7))
                   1010:                        printf("btree: level %d\n", level);
                   1011: #              endif
                   1012:                dirbuf.mainpg = level;
                   1013:                dirbuf.thispage = stop + 1;
                   1014:                dirbuf.ovflopg = dirbuf.thispage + 1;
                   1015:                dirbuf.linetab[0] = (short) (&dirbuf.firstup[PGPTRSIZ] - (char *) &dirbuf);
                   1016: 
                   1017:                stuff_page(dirbuf.firstup, &start);     /* put first pgnum in */
                   1018:                start++;
                   1019: 
                   1020:                offset = dirbuf.linetab[0];
                   1021:                dirbuf.bufstatus = BUF_DIRTY | BUF_DIRECT;
                   1022: 
                   1023:                dirbuf.nxtlino = 0;
                   1024:                newstart = stop + 1;
                   1025:                newstop = newstart;
                   1026:                for (pageid = start; pageid <= stop; pageid++)
                   1027:                {
                   1028: #                      ifdef xZTR2
                   1029:                        if (tTf(38, 8))
                   1030:                                printf("btree:get key from %ld\n", pageid);
                   1031: #                      endif
                   1032:                        stuff_page(tid, &pageid);
                   1033:                        tid->line_id = 0;
                   1034:                        if (tmp = get(d, tid, tid, &tuple, FALSE))
                   1035:                        {
                   1036:                                syserr("modify: bldbindex: get %d\n", tmp);
                   1037:                        }
                   1038: 
                   1039:                        /*
                   1040:                        ** If this is the first level then form the tuple
                   1041:                        ** from the mainpage of the relation. Otherwise
                   1042:                        ** the tuple is the first tuple of a directory page
                   1043:                        ** and it is already correctly formed.
                   1044:                        */
                   1045:                        if (level == 0)
                   1046:                        {
                   1047:                                bndxkey(d, tuple.childtup, &temptup, &pageid, keyx);
                   1048:                                /*
                   1049:                                stuff_page(&temptup.childtid, &pageid);
                   1050:                                key = temptup.childtup;
                   1051:                                for (tmp = 0; keyx[tmp] != 0; tmp++)
                   1052:                                {
                   1053:                                        len = d->relfrml[keyx[tmp]] & I1MASK;
                   1054:                                        bmove(&((char *) &tuple)[d->reloff[keyx[tmp]]], key, len);
                   1055:                                        key += len;
                   1056:                                }
                   1057:                                */
                   1058: 
                   1059:                                
                   1060:                                printf("primary ");
                   1061:                                key = &temptup;
                   1062:                        }
                   1063:                        else
                   1064:                        {
                   1065:                                stuff_page(&tuple.childtid, &pageid);
                   1066:                                key = &tuple;
                   1067:                                printf("secondary %d: ", level);
                   1068:                        }
                   1069: 
                   1070:                        printf("adding: ");
                   1071:                        prbndxkey(d, key, keyx);
                   1072:                        printf("\n");
                   1073: 
                   1074:                        if (fill_leave > space_left(&dirbuf))
                   1075:                        {
                   1076:                                if (pageflush(&dirbuf))
                   1077:                                        return (-3);
                   1078:                                dirbuf.thispage++;
                   1079:                                newstop = dirbuf.thispage;
                   1080:                                dirbuf.ovflopg = dirbuf.thispage + 1;
                   1081:                                dirbuf.linetab[0] = (short) (&dirbuf.firstup[PGPTRSIZ] - (char *) &dirbuf);
                   1082: 
                   1083:                                stuff_page(dirbuf.firstup, &pageid);
                   1084: 
                   1085:                                offset = dirbuf.linetab[0];
                   1086:                                dirbuf.bufstatus = BUF_DIRTY;
                   1087:                                dirbuf.nxtlino = 0;
                   1088:                                continue;
                   1089:                        }
                   1090:                        /* copy key to directory page */
                   1091:                        bmove(key, (char *) &dirbuf + offset, keywid);
                   1092: 
                   1093:                        /* update next line number */
                   1094:                        offset += keywid;
                   1095:                        dirbuf.nxtlino++;
                   1096:                        dirbuf.linetab[-dirbuf.nxtlino] = offset;
                   1097:                }
                   1098:                if (newstart == newstop)                /* must be root */
                   1099:                        dirbuf.thispage = 0;            /* root is page 0 */
                   1100: 
                   1101:                dirbuf.ovflopg = 0;                     /* no more pages */
                   1102: 
                   1103:                if (pageflush(&dirbuf))
                   1104:                        return (-4);
                   1105: 
                   1106:                if (newstart == newstop)
                   1107:                        break;
                   1108:                d->reldum.relspec = abs(d->reldum.relspec);
                   1109:                level++;
                   1110:                start = newstart;
                   1111:                stop = newstop;
                   1112:        }
                   1113:        d->reldum.relspec = savespec;
                   1114:        d->reldum.relprim = newstart;
                   1115:        return (0);
                   1116: }
                   1117: /*
                   1118: **     UNSPOOL -- Take tuples saved in spool file and insert them
                   1119: **             in new relation.  This is only for ISAM relations.
                   1120: */
                   1121: 
                   1122: unspool(descx)
                   1123: DESC   *descx;
                   1124: {
                   1125:        register DESC   *desc;
                   1126:        register int    i;
                   1127:        TID             tid;
                   1128:        char            tup_buf[MAXTUP], spoolbuf[IOBUFSIZ];
                   1129:        FILE            *spfp;
                   1130: 
                   1131:        desc = descx;
                   1132:        if (Mod_info.spflag)
                   1133:        {
                   1134:                if ((spfp = fopen(Mod_info.spfile, "read", spoolbuf)) == NULL)
                   1135:                        syserr("UNSPOOL: fopen spool");
                   1136:                while ((i = fread(spfp, tup_buf, desc->reldum.relwid)) == desc->reldum.relwid)
                   1137:                        if ((i = insert(desc, &tid, tup_buf, FALSE)) < 0)
                   1138:                                syserr("UNSPOOL: insert %.14s %d", desc->reldum.relid, i);
                   1139:                if (i != 0)
                   1140:                        syserr("UNSPOOL: read %d", i);
                   1141:                fclose(spfp);
                   1142:                unlink(Mod_info.spfile);
                   1143:        }
                   1144:        desc->reldum.reltups += desc->reladds;
                   1145:        desc->reladds = 0;
                   1146:        return (0);
                   1147: }
                   1148: /*
                   1149: **     FILL_BATCH -- Create and fill a batch file containing the
                   1150: **             updates for the system catalog so that MODIFY will
                   1151: **             be recoverable if the system crashes.
                   1152: */
                   1153: 
                   1154: fill_batch(odesc, descx)
                   1155: DESC   *odesc, *descx;
                   1156: {
                   1157:        register DESC           *desc, *dessys;
                   1158:        register int            i;
                   1159:        struct relation         reltup, rkey;
                   1160:        TID                     tid, lotid, hitid;
                   1161:        struct attribute        atttup, akey;
                   1162:        int                     j;
                   1163:        char                    prebatch[MAXNAME + 4], modbatch[MAXNAME + 4];
                   1164: 
                   1165:        desc = descx;
                   1166:        if (bequal(desc->reldum.relid, "relation    ", 12))
                   1167:        {
                   1168:                clearkeys(desc);
                   1169:                setkey(desc, &rkey, desc->reldum.relid, RELID);
                   1170:                setkey(desc, &rkey, desc->reldum.relowner, RELOWNER);
                   1171:                if (i = getequal(desc, &rkey, &reltup, &tid))
                   1172:                        syserr("FILL_BATCH: geteq rel rel %d", i);
                   1173:                bmove(&tid, &desc->reltid, sizeof desc->reltid);
                   1174:        }
                   1175:        else
                   1176:                bmove(&odesc->reltid, &desc->reltid, sizeof desc->reltid);
                   1177:        resetacc(Acc_head);
                   1178:        concat(MOD_PREBATCH, Fileset, prebatch);
                   1179:        close(creat(prebatch, FILEMODE));
                   1180:        if ((Batch_fp = open(prebatch, 2)) < 0)
                   1181:                syserr("FILL_BATCH: open %.14s %d", prebatch, Batch_fp);
                   1182:        smove(Fileset, Batchbuf.file_id);
                   1183:        Batch_cnt = 0;
                   1184:        wrbatch(desc, sizeof *desc);
                   1185:        if (bequal(desc->reldum.relid, "attribute   ", 12))
                   1186:                dessys = desc;
                   1187:        else
                   1188:                dessys = &Admin.adattd;
                   1189:        clearkeys(dessys);
                   1190:        setkey(dessys, &akey, desc->reldum.relid, ATTRELID);
                   1191:        setkey(dessys, &akey, desc->reldum.relowner, ATTOWNER);
                   1192:        if (i = find(dessys, EXACTKEY, &lotid, &hitid, &akey))
                   1193:                syserr("FILL_BATCH: find %d", i);
                   1194:        j = desc->reldum.relatts;
                   1195:        while(!(i = get(dessys, &lotid, &hitid, &atttup, TRUE)) && j > 0)
                   1196:                if (!kcompare(dessys, &akey, &atttup))
                   1197:                {
                   1198:                        j--;
                   1199:                        atttup.attxtra = desc->relxtra[atttup.attid];
                   1200:                        wrbatch(&lotid, sizeof lotid);
                   1201:                        wrbatch(&atttup, sizeof atttup);
                   1202:                }
                   1203:        if (i < 0 || j > 0)
                   1204:                syserr("FILL_BATCH: get att %d count %d", i, j);
                   1205:        /* get rid of attribute pages */
                   1206:        cleanrel(dessys);
                   1207:        flushbatch();
                   1208:        close(Batch_fp);
                   1209:        concat(MODBATCH, Fileset, modbatch);
                   1210:        if (link(prebatch, modbatch) == -1)
                   1211:                syserr("FILL_BATCH: can't link %.14s %.14s",
                   1212:                        prebatch, modbatch);
                   1213:        unlink(prebatch);
                   1214:        return (0);
                   1215: 
                   1216: }

unix.superglobalmegacorp.com

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