home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / LAR_C86.ZIP / LAR_C86.C
Text File  |  1989-03-20  |  18KB  |  791 lines

  1. /*% cc -O lar.c -o lar
  2. From linus!sch Tue Jul 26 08:07:37 1983
  3. Subject: CP/M Lu library maintainer
  4.  
  5. When transfering files to my personal computer, I often want to transfer
  6. several files at once using the Umodem program.  To do this I wrote
  7. the following small program to combine files for the CP/M LU program.
  8.  
  9. No special treatment necessary, just:
  10.     cc -O lar.c -o lar
  11. to make it.
  12.  
  13. -- 
  14. Stephen Hemminger,  Mitre Corp. Bedford MA 
  15.     {allegra,genrad,ihnp4, utzoo}!linus!sch    (UUCP)
  16.     linus!sch@mitre-bedford            (ARPA)
  17. ----------------- lar.c ----------------------
  18. */
  19. /* May 1985  J. P. Worth
  20.     Modifications and enhancements to original UNIX  c source
  21.     to allow operation under CP/M, MS/DOS and compilation with
  22.     the CI C86 compiler. All changes are transparent to the
  23.     original lar.c source through the use of a define variable
  24.     "C86". Compile using as one of the options  "-dC86" or
  25.     include "#define    C86" as first line of source code
  26.     All features checked and tested under CP/M 86 with Version
  27.     2.20H of CI C86 compiler
  28. */
  29.  
  30. /*
  31.  * Lar - LU format library file maintainer
  32.  * by Stephen C. Hemminger
  33.  *    linus!sch    or    sch@Mitre-Bedford
  34.  *
  35.  *  Usage: lar key library [files] ...
  36.  *
  37.  *  Key functions are:
  38.  *    u - Update, add files to library
  39.  *    t - Table of contents
  40.  *    e - Extract files from library
  41.  *    p - Print files in library
  42.  *    d - Delete files in library
  43.  *    r - Reorginize library
  44.  *  Other keys:
  45.  *    v - Verbose
  46.  *
  47.  *  This program is public domain software, no warranty intended or
  48.  *  implied.
  49.  *
  50.  *  DESCRPTION
  51.  *     Lar is a Unix program to manipulate CP/M LU format libraries.
  52.  *     The original CP/M library program LU is the product
  53.  *     of Gary P. Novosielski. The primary use of lar is to combine several
  54.  *     files together for upload/download to a personal computer.
  55.  *
  56.  *  PORTABILITY
  57.  *     The code is modeled after the Software tools archive program,
  58.  *     and is setup for Version 7 Unix.  It does not make any assumptions
  59.  *     about byte ordering, explict and's and shift's are used.
  60.  *     If you have a dumber C compiler, you may have to recode new features
  61.  *     like structure assignment, typedef's and enumerated types.
  62.  *
  63.  *  BUGS/MISFEATURES
  64.  *     The biggest problem is text files, the programs tries to detect
  65.  *     text files vs. binaries by checking for non-Ascii (8th bit set) chars.
  66.  *     If the file is text then it will throw away Control-Z chars which
  67.  *     CP/M puts on the end.  All files in library are padded with Control-Z
  68.  *     at the end to the CP/M sector size if necessary.
  69.  *
  70.  *     No effort is made to handle the difference between CP/M and Unix
  71.  *     end of line chars.  CP/M uses Cr/Lf and Unix just uses Lf.
  72.  *     The solution is just to use the Unix command sed when necessary.
  73.  *
  74.  *  * Unix is a trademark of Bell Labs.
  75.  *  ** CP/M is a trademark of Digital Research.
  76.  */
  77.  
  78. #include <stdio.h>
  79. #include <ctype.h>
  80. #define    C86
  81.  
  82. #define ACTIVE    00
  83. #define UNUSED    0xff
  84. #define DELETED 0xfe
  85. #define CTRLZ    0x1a
  86.  
  87. #define MAXFILES 256
  88. #define SECTOR     128
  89. #define DSIZE    ( sizeof(struct ludir) )
  90. #define SLOTS_SEC (SECTOR/DSIZE)
  91. #define equal(s1, s2) ( strcmp(s1,s2) == 0 )
  92. /* if you don't have void type just define as blank */
  93. #ifndef    C86
  94.  
  95. #define    VOID    (void)
  96.  
  97. #else
  98.  
  99. #define VOID    
  100.  
  101. #endif
  102.  
  103. /* if no enum's then define false as 0 and true as 1 and bool as int */
  104.  
  105. #ifndef    C86
  106. typedef enum {false=0, true=1} bool;
  107.  
  108.  
  109.  
  110. #else
  111. #define    false    0
  112. #define    true    1
  113.  
  114.  
  115. #define    bool    int
  116.  
  117. #endif
  118.  
  119.  
  120. /* Globals */
  121. char   *fname[MAXFILES];
  122. bool ftouched[MAXFILES];
  123.  
  124. typedef struct {
  125.     unsigned char   lobyte;
  126.     unsigned char   hibyte;
  127. } word;
  128.  
  129. /* convert word to int */
  130. #define wtoi(w) ( (w.hibyte<<8) + w.lobyte)
  131. #define itow(dst,src)    dst.hibyte = (src & 0xff00) >> 8;\
  132.                 dst.lobyte = src & 0xff;
  133.  
  134. struct ludir {            /* Internal library ldir structure */
  135.     unsigned char   l_stat;    /*  status of file */
  136.     char    l_name[8];        /*  name */
  137.     char    l_ext[3];        /*  extension */
  138.     word    l_off;        /*  offset in library */
  139.     word    l_len;        /*  lengty of file */
  140.     char    l_fill[16];        /*  pad to 32 bytes */
  141. } ldir[MAXFILES];
  142.  
  143. int     errcnt, nfiles, nslots;
  144. bool    verbose = false;
  145. char    *cmdname;
  146.  
  147. char   *getname(), *sprintf();
  148. int    update(), reorg(), table(), extract(), print(), delete();
  149. #ifdef    C86
  150. long    rewind(), ftell(), fseek();
  151. #endif
  152.  
  153. main (argc, argv)
  154. int    argc;
  155. char  **argv;
  156. {
  157.     register char *flagp;
  158.     char   *aname;            /* name of library file */
  159.     int       (*function)() = NULL;    /* function to do on library */
  160. /* set the function to be performed, but detect conflicts */
  161. #define setfunc(val)    if(function != NULL) conflict(); else function = val
  162.  
  163.     cmdname = "lar";    /* can't get command name in CPM with argv[0] */
  164.     if (argc < 3)
  165.     help ();
  166.  
  167.     aname = argv[2];
  168.     filenames (argc, argv);
  169.  
  170.     for(flagp = argv[1]; *flagp; flagp++)
  171.     switch (*flagp) {
  172.     case '-':
  173.         break;
  174.     case 'u': 
  175.         setfunc(update);
  176.         break;
  177.     case 't': 
  178.         setfunc(table);
  179.         break;
  180.     case 'e': 
  181.         setfunc(extract);
  182.         break;
  183.     case 'p': 
  184.         setfunc(print);
  185.         break;
  186.     case 'd': 
  187.         setfunc(delete);
  188.         break;
  189.     case 'r': 
  190.         setfunc(reorg);
  191.         break;
  192.     case 'v':
  193.         verbose = true;
  194.         break;
  195.     default: 
  196.         help ();
  197.     }
  198.  
  199.     if(function == NULL) {
  200.     fprintf(stderr,"No function key letter specified\n");
  201.     help();
  202.     }
  203.  
  204.     (*function)(aname);
  205. }
  206.  
  207. /* print error message and exit */
  208. help () {
  209.     fprintf (stderr, "Usage: %s {utepdr}[v] library [files] ...\n", cmdname);
  210.     fprintf (stderr, "Functions are:\n\tu - Update, add files to library\n");
  211.     fprintf (stderr, "\tt - Table of contents\n");
  212.     fprintf (stderr, "\te - Extract files from library\n");
  213.     fprintf (stderr, "\tp - Print files in library\n");
  214.     fprintf (stderr, "\td - Delete files in library\n");
  215.     fprintf (stderr, "\tr - Reorginize library\n");
  216.  
  217.     fprintf (stderr, "Flags are:\n\tv - Verbose\n");
  218.     exit (1);
  219. }
  220.  
  221. conflict() {
  222.    fprintf(stderr,"Conficting keys\n");
  223.    help();
  224. }
  225.  
  226. error (str)
  227. char   *str;
  228. {
  229.     fprintf (stderr, "%s: %s\n", cmdname, str);
  230.     exit (1);
  231. }
  232.  
  233.  
  234. /* Get file names, check for dups, and initialize */
  235. filenames (ac, av)
  236. char  **av;
  237. {
  238.     register int    i, j;
  239.  
  240.     errcnt = 0;
  241.     for (i = 0; i < ac - 3; i++) {
  242.     fname[i] = av[i + 3];
  243.     ftouched[i] = false;
  244.     if (i == MAXFILES)
  245.         error ("Too many file names.");
  246.     }
  247.     fname[i] = NULL;
  248.     nfiles = i;
  249.     for (i = 0; i < nfiles; i++)
  250.     for (j = i + 1; j < nfiles; j++)
  251.         if (equal (fname[i], fname[j])) {
  252.         fprintf (stderr, "%s", fname[i]);
  253.         error (": duplicate file name");
  254.         }
  255. }
  256.  
  257. table (lib)
  258. char   *lib;
  259. {
  260.     FILE   *lfd;
  261.     register int    i, total;
  262.     int active = 0, unused = 0, deleted = 0;
  263.     char *uname;
  264.  
  265. #ifndef    C86
  266.     if ((lfd = fopen (lib, "r")) == NULL) {
  267. #else
  268.     if ((lfd = fopen (lib, "rb")) == NULL) {
  269. #endif
  270.     fprintf(stderr, "%s: can't open\n", lib);
  271.     exit(1);
  272.     }
  273.  
  274.     getdir (lfd);
  275.     total = wtoi(ldir[0].l_len);
  276.     if(verbose) {
  277.      printf("Name          Index Length\n");
  278.     printf("Directory           %4d\n", total);
  279.     }
  280.  
  281.     for (i = 1; i < nslots; i++)
  282.     switch(ldir[i].l_stat) {
  283.     case ACTIVE:
  284.         active++;
  285.         uname = getname(ldir[i].l_name, ldir[i].l_ext);
  286.         if (filarg (uname))
  287.             if(verbose) 
  288.             printf ("%-12s   %4d %4d\n", uname,
  289.                 wtoi (ldir[i].l_off), wtoi (ldir[i].l_len));
  290.             else
  291.             printf ("%s\n", uname);
  292.         total += wtoi(ldir[i].l_len);
  293.         break;
  294.     case UNUSED:
  295.         unused++;
  296.         break;
  297.     default:
  298.         deleted++;
  299.     }
  300.     if(verbose) {
  301.     printf("--------------------------\n");
  302.     printf("Total sectors       %4d\n", total);
  303.     printf("\nLibrary %s has %d slots, %d deleted %d active, %d unused\n",
  304.         lib, nslots, deleted, active, unused);
  305.     }
  306.  
  307.     VOID fclose (lfd);
  308.     not_found ();
  309. }
  310.  
  311. getdir (f)
  312. FILE *f;
  313. {
  314.  
  315.     rewind(f);
  316.  
  317.     if (fread ((char *) & ldir[0], DSIZE, 1, f) != 1)
  318.     error ("No directory\n");
  319.  
  320.     nslots = wtoi (ldir[0].l_len) * SLOTS_SEC;
  321.  
  322.     if ( fread( (char *) & ldir[1], DSIZE, nslots, f) != nslots)
  323.     error("Can't read directory - is it a library?");
  324. }
  325.  
  326. putdir (f)
  327. FILE *f;
  328. {
  329.  
  330.     rewind(f);
  331.     if (fwrite ((char *) ldir, DSIZE, nslots, f) != nslots)
  332.     error ("Can't write directory - library may be botched");
  333. }
  334.  
  335. initdir (f)
  336. FILE *f;
  337. {
  338.     register int    i, j;
  339.     int     numsecs;
  340.     char    line[80];
  341.     static struct ludir blankentry = {
  342.     UNUSED,
  343.     { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
  344.     { ' ', ' ', ' ' },
  345.     };
  346.  
  347.     for (;;) {
  348.     printf ("Number of slots to allocate (multiple of 8):  ");
  349.     if (fgets (line, 80, stdin) == NULL)
  350.         error ("Eof when reading input");
  351.     nslots = atoi (line);
  352.     if (nslots < 1)
  353.         printf ("Must have at least one!\n");
  354.     else if (nslots > MAXFILES)
  355.         printf ("Too many slots\n");
  356.     else
  357.         break;
  358.     }
  359.  
  360.     numsecs = nslots / SLOTS_SEC;
  361.     nslots = numsecs * SLOTS_SEC;
  362.  
  363.     for (i = 0; i < nslots; i++) {
  364.  
  365. #ifndef    C86
  366.     ldir[i] = blankentry;
  367. #else
  368.  
  369.  
  370.     for(j = 0; j < 16; j++) {
  371.         ldir[i].l_ext[j%3] = blankentry.l_ext[j%3];
  372.         ldir[i].l_name[j%8] = blankentry.l_name[j%8];
  373.         ldir[i].l_fill[j] = blankentry.l_fill[j];
  374.     }
  375.     ldir[i].l_stat = blankentry.l_stat;
  376. #endif
  377.     }
  378.     ldir[0].l_stat = ACTIVE;
  379.     itow (ldir[0].l_len, numsecs);
  380.  
  381.     putdir (f);
  382. }
  383.  
  384. /* convert nm.ex to a Unix style string */
  385. char   *getname (nm, ex)
  386. char   *nm, *ex;
  387. {
  388.     static char namebuf[14];
  389.     register char  *cp, *dp;
  390.  
  391.     for (cp = namebuf, dp = nm; *dp != ' ' && dp != &nm[8];) {
  392.     *cp++ = isupper (*dp) ? tolower (*dp) : *dp;
  393.     ++dp;
  394.     }
  395.     *cp++ = '.';
  396.  
  397.     for (dp = ex; *dp != ' ' && dp != &ex[3];) {
  398.     *cp++ = isupper (*dp) ? tolower (*dp) : *dp;
  399.     ++dp;
  400.     }
  401.  
  402.     *cp = '\0';
  403.     return namebuf;
  404. }
  405.  
  406. putname (cpmname, unixname)
  407. char   *cpmname, *unixname;
  408. {
  409.     register char  *p1, *p2;
  410.  
  411.     for (p1 = unixname, p2 = cpmname; *p1; p1++, p2++) {
  412.     while (*p1 == '.') {
  413.         p2 = cpmname + 8;
  414.         p1++;
  415.     }
  416.     if (p2 - cpmname < 11)
  417.         *p2 = islower(*p1) ? toupper(*p1) : *p1;
  418.     else {
  419.         fprintf (stderr, "%s: name truncated\n", unixname);
  420.         break;
  421.     }
  422.     }
  423.     while (p2 - cpmname < 11)
  424.     *p2++ = ' ';
  425. }
  426.  
  427. /* filarg - check if name matches argument list */
  428. filarg (name)
  429. char   *name;
  430. {
  431.     register int    i;
  432.     char *strpname;
  433.  
  434.     if (nfiles <= 0)
  435.     return 1;
  436.  
  437.     for (i = 0; i < nfiles; i++) {
  438. /* the following is a hack to strip the drive label and colon 
  439.    for use under CPM, MSDOS, etc  may 85 jpw   */
  440.     strpname = fname[i];
  441.     if ( *(fname[i] + 1) == ':')  strpname = fname[i] + 2;
  442.     if (equal (name, strpname)) {
  443.         ftouched[i] = true;
  444.         return 1;
  445.     }
  446.     }
  447.  
  448.     return 0;
  449. }
  450.  
  451. not_found () {
  452.     register int    i;
  453.  
  454.     for (i = 0; i < nfiles; i++)
  455.     if (!ftouched[i]) {
  456.         fprintf (stderr, "%s: not in library.\n", fname[i]);
  457.         errcnt++;
  458.     }
  459. }
  460.  
  461.  
  462. extract(name)
  463. char *name;
  464. {
  465.     getfiles(name, false);
  466. }
  467.  
  468. print(name)
  469. char *name;
  470. {
  471.     getfiles(name, true);
  472. }
  473.  
  474. getfiles (name, pflag)
  475. char   *name;
  476. bool    pflag;
  477. {
  478.     FILE *lfd, *ofd;
  479.     register int    i;
  480.     char   *unixname;
  481.  
  482. #ifndef    C86
  483.     if ((lfd = fopen (name, "r")) == NULL) {
  484. #else
  485.     if ((lfd = fopen (name, "rb"))  == NULL) {
  486. #endif
  487.     fprintf(stderr, "%s: can't open\n", name);
  488.     exit(1);
  489.     }
  490.  
  491.     ofd = pflag ? stdout : NULL;
  492.     getdir (lfd);
  493.  
  494.     for (i = 1; i < nslots; i++) {
  495.     if(ldir[i].l_stat != ACTIVE)
  496.         continue;
  497.     unixname = getname (ldir[i].l_name, ldir[i].l_ext);
  498.     if (!filarg (unixname))
  499.         continue;
  500.     fprintf(stderr,"%s", unixname);
  501.     if (ofd != stdout)
  502. #ifndef    C86
  503.         ofd = fopen (unixname, "w");
  504. #else
  505.         ofd = fopen (unixname, "wb");
  506. #endif
  507.     if (ofd == NULL) {
  508.         fprintf (stderr, "  - can't create");
  509.         errcnt++;
  510.     }
  511.     else {
  512.         VOID fseek (lfd, (long) wtoi (ldir[i].l_off) * SECTOR, 0);
  513.         acopy (lfd, ofd, wtoi (ldir[i].l_len));
  514.         if (ofd != stdout)
  515.         VOID fclose (ofd);
  516.     }
  517.     putc('\n', stderr);
  518.     }
  519.     VOID fclose (lfd);
  520.     not_found ();
  521. }
  522.  
  523. acopy (fdi, fdo, nsecs)
  524. FILE *fdi, *fdo;
  525. register unsigned int nsecs;
  526. {
  527.     register int    i, c;
  528.     int        textfile = 1;
  529.  
  530.     while( nsecs-- != 0) 
  531.     for(i=0; i<SECTOR; i++) {
  532.         c = getc(fdi);
  533. #ifndef    C86
  534.         if( feof(fdi) )
  535. #else
  536.         if( c == EOF )
  537. #endif
  538.             error("Premature EOF\n");
  539.         if( ferror(fdi) )
  540.             error ("Can't read");
  541.         if( !isascii(c) )
  542.             textfile = 0;
  543.         if( nsecs != 0 || !textfile || c != CTRLZ) {
  544.             putc(c, fdo);
  545.             if ( ferror(fdo) )
  546.                 error ("write error");
  547.         }
  548.      }
  549. }
  550.  
  551. update (name)
  552. char   *name;
  553. {
  554.     FILE *lfd;
  555.     register int    i;
  556.  
  557. #ifndef    C86
  558.    if ((lfd = fopen (name, "r+")) == NULL) {
  559. #else
  560.     if ((lfd = fopen (name, "rwb")) == NULL) {
  561. #endif
  562. #ifndef    C86
  563.     if ((lfd = fopen (name, "w+")) == NULL) {
  564. #else
  565.     if ((lfd = fopen (name, "wrb")) == NULL) {
  566. #endif
  567.     fprintf(stderr, "%s: can't open or create for update\n", name);
  568.     exit(1);
  569.     }
  570.     initdir (lfd);
  571.     }
  572.     else
  573.     getdir (lfd);        /* read old directory */
  574.  
  575.     if(verbose)
  576.         fprintf (stderr,"Updating files:\n");
  577.     for (i = 0; i < nfiles; i++)
  578.     addfil (fname[i], lfd);
  579.     if (errcnt == 0)
  580.     putdir (lfd);
  581.     else
  582.     fprintf (stderr, "fatal errors - library not changed\n");
  583.     VOID fclose (lfd);
  584. }
  585.  
  586. addfil (name, lfd)
  587. char   *name;
  588. FILE *lfd;
  589. {
  590.     FILE    *ifd;
  591.     register int secoffs, numsecs;
  592.     register int i;
  593.  
  594. #ifndef    C86
  595.     if ((ifd = fopen (name, "r")) == NULL) {
  596. #else
  597.     if ((ifd = fopen (name, "rb")) == NULL) {
  598. #endif
  599.     fprintf (stderr, "%s: can't find to add\n",name);
  600.     errcnt++;
  601.     return;
  602.     }
  603.  /* the following line is to remove drive label and colon if present 
  604.     may 85 jpw */
  605.     if ( *(name+1) == ':')   name +=2 ;
  606.     if(verbose)
  607.         fprintf(stderr, "%s\n", name);
  608.     for (i = 0; i < nslots; i++) {
  609.     if (equal( getname (ldir[i].l_name, ldir[i].l_ext), name) ) /* update */
  610.         break;
  611.     if (ldir[i].l_stat != ACTIVE)
  612.         break;
  613.     }
  614.     if (i >= nslots) {
  615.     fprintf (stderr, "%s: can't add library is full\n",name);
  616.     errcnt++;
  617.     return;
  618.     }
  619.  
  620.     ldir[i].l_stat = ACTIVE;
  621.     putname (ldir[i].l_name, name);
  622.     VOID fseek(lfd, 0L, 2);        /* append to end */
  623.     secoffs =  (ftell(lfd) / SECTOR);
  624.  
  625.     itow (ldir[i].l_off, (unsigned) secoffs);
  626.     numsecs = fcopy (ifd, lfd);
  627.     itow (ldir[i].l_len, numsecs);
  628.     VOID fclose (ifd);
  629. }
  630.  
  631. fcopy (ifd, ofd)
  632. FILE *ifd, *ofd;
  633. {
  634.     register int total = 0;
  635.     register int i, n;
  636.     char sectorbuf[SECTOR];
  637.  
  638.  
  639.     while ( (n = fread( sectorbuf, 1, SECTOR, ifd)) != 0) {
  640.     if (n != SECTOR)
  641.         for (i = n; i < SECTOR; i++)
  642.         sectorbuf[i] = CTRLZ;
  643.     if (fwrite( sectorbuf, 1, SECTOR, ofd ) != SECTOR)
  644.         error("write error");
  645.     ++total;
  646.     }
  647.     return total;
  648. }
  649.  
  650. delete (lname)
  651. char   *lname;
  652. {
  653.     FILE *f;
  654.     register int    i, j;
  655.  
  656. #ifndef    C86
  657.     if ((f = fopen (lname, "r+")) == NULL) {
  658. #else
  659.     if ((f = fopen (lname, "rwb")) == NULL) {
  660. #endif
  661.     fprintf(stderr, "%s: can't open\n", lname);
  662.     exit(1);
  663.     }
  664.  
  665.     if (nfiles <= 0)
  666.     error("delete by name only");
  667.  
  668.     getdir (f);
  669.     for (i = 0; i < nslots; i++) {
  670.     if (!filarg ( getname (ldir[i].l_name, ldir[i].l_ext)))
  671.         continue;
  672.     ldir[i].l_stat = DELETED;
  673.     for (j = 0; j < 8; j++) {
  674.         ldir[i].l_ext[j%3] = ' ';
  675.         ldir[i].l_name[j] = ' ';
  676.     }
  677.     }
  678.  
  679.     not_found();
  680.     if (errcnt > 0)
  681.     fprintf (stderr, "errors - library not updated\n");
  682.     else
  683.     putdir (f);
  684.     VOID fclose (f);
  685. }
  686.  
  687. reorg (name)
  688. char  *name;
  689. {
  690.     FILE *olib, *nlib;
  691.     int oldsize;
  692.     register int i, j;
  693.     struct ludir odir[MAXFILES];
  694.     char tmpname[SECTOR];
  695.  
  696.     VOID sprintf(tmpname,"%-10.10s.TMP", name);
  697.  
  698. #ifndef    C86
  699.     if( (olib = fopen(name,"r")) == NULL) {
  700. #else
  701.     if( (olib = fopen(name,"rb")) == NULL) {
  702. #endif
  703.     fprintf(stderr, "%s: can't open\n", name);
  704.     exit(1);
  705.     }
  706.  
  707. #ifndef    C86
  708.     if( (nlib = fopen(tmpname, "w")) == NULL) {
  709. #else
  710.     if( (nlib = fopen(tmpname, "wb")) == NULL) {
  711. #endif
  712.     fprintf(stderr, "%s: can't open\n", tmpname);
  713.     exit(1);
  714.     }
  715.  
  716.     getdir(olib);
  717.     printf("Old library has %d slots\n", oldsize = nslots);
  718.     for(i = 0; i < nslots ; i++)
  719.         copymem( (char *) &odir[i], (char *) &ldir[i],
  720.             sizeof(struct ludir));
  721.     initdir(nlib);
  722.     errcnt = 0;
  723.  
  724.     for (i = j = 1; i < oldsize; i++)
  725.     if( odir[i].l_stat == ACTIVE ) {
  726.         if(verbose)
  727.         fprintf(stderr, "Copying: %-8.8s.%3.3s\n",
  728.             odir[i].l_name, odir[i].l_ext);
  729.         copyentry( &odir[i], olib,  &ldir[j], nlib);
  730.         if (++j >= nslots) {
  731.         errcnt++;
  732.         fprintf(stderr, "Not enough room in new library\n");
  733.         break;
  734.         }
  735.         }
  736.  
  737.     VOID fclose(olib);
  738.     putdir(nlib);
  739.     VOID fclose (nlib);
  740.  
  741.     if(errcnt == 0) {
  742. #ifndef    C86
  743.     if ( unlink(name) < 0 || link(tmpname, name) < 0) {
  744. #else
  745.     if ( unlink(name) < 0 || rename(tmpname, name) < 0) {
  746. #endif
  747.         VOID unlink(tmpname);
  748.     fprintf(stderr, "%s: can't delete or rename\n", name);
  749.     exit(1);
  750.     }
  751.     }
  752.     else
  753.     fprintf(stderr,"Errors, library not updated\n");
  754.     VOID unlink(tmpname);
  755.  
  756. }
  757.  
  758. copyentry( old, of, new, nf )
  759. struct ludir *old, *new;
  760. FILE *of, *nf;
  761. {
  762.     register int secoffs, numsecs;
  763.     char buf[SECTOR];
  764.  
  765.     new->l_stat = ACTIVE;
  766.     copymem(new->l_name, old->l_name, 8);
  767.     copymem(new->l_ext, old->l_ext, 3);
  768.     VOID fseek(of, (long) wtoi(old->l_off)*SECTOR, 0);
  769.     VOID fseek(nf, 0L, 2);
  770.     secoffs = ftell(nf) / SECTOR;
  771.  
  772.     itow (new->l_off, secoffs);
  773.     numsecs = wtoi(old->l_len);
  774.     itow (new->l_len, numsecs);
  775.  
  776.     while(numsecs-- != 0) {
  777.     if( fread( buf, 1, SECTOR, of) != SECTOR)
  778.         error("read error");
  779.     if( fwrite( buf, 1, SECTOR, nf) != SECTOR)
  780.         error("write error");
  781.     }
  782. }
  783.  
  784. copymem(dst, src, n)
  785. register char *dst, *src;
  786. register unsigned int n;
  787. {
  788.     while(n-- != 0)
  789.         *dst++ = *src++;
  790. }
  791.