home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / ranlib / build.c next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  7.5 KB  |  280 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Hugh Smith at The University of Guelph.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)build.c    5.3 (Berkeley) 3/12/91";
  39. #endif /* not lint */
  40.  
  41. #include <sys/types.h>
  42. #include <sys/errno.h>
  43. #include <sys/stat.h>
  44. #include <fcntl.h>
  45. #include <a.out.h>
  46. #include <dirent.h>
  47. #include <unistd.h>
  48. #include <ar.h>
  49. #include <ranlib.h>
  50. #include <stdio.h>
  51. #include <archive.h>
  52.  
  53. extern CHDR chdr;            /* converted header */
  54. extern char *archive;            /* archive name */
  55. extern char *tname;            /* temporary file "name" */
  56.  
  57. typedef struct _rlib {
  58.     struct _rlib *next;        /* next structure */
  59.     off_t pos;            /* offset of defining archive file */
  60.     char *sym;            /* symbol */
  61.     int symlen;            /* strlen(sym) */
  62. } RLIB;
  63. RLIB *rhead, **pnext;
  64.  
  65. FILE *fp;
  66. static void rexec(), symobj();
  67.  
  68. build()
  69. {
  70.     CF cf;
  71.     int afd, tfd;
  72.     off_t size;
  73.  
  74.     afd = open_archive(O_RDWR);
  75.     fp = fdopen(afd, "r+");
  76.     tfd = tmp();
  77.  
  78.     SETCF(afd, archive, tfd, tname, RPAD|WPAD);
  79.  
  80.     /* Read through the archive, creating list of symbols. */
  81.     pnext = &rhead;
  82.     while(get_arobj(afd)) {
  83.         if (!strcmp(chdr.name, RANLIBMAG)) {
  84.             skip_arobj(afd);
  85.             continue;
  86.         }
  87.         rexec(afd, tfd);
  88.         put_arobj(&cf, (struct stat *)NULL);
  89.     }
  90.     *pnext = NULL;
  91.  
  92.     /* Create the symbol table. */
  93.     symobj();
  94.  
  95.     /* Copy the saved objects into the archive. */
  96.     size = lseek(tfd, (off_t)0, SEEK_CUR);
  97.     (void)lseek(tfd, (off_t)0, SEEK_SET);
  98.     SETCF(tfd, tname, afd, archive, RPAD|WPAD);
  99.     copy_ar(&cf, size);
  100.     (void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR));
  101.     (void)close(tfd);
  102.  
  103.     /* Set the time. */
  104.     settime(afd);
  105.     close_archive(afd);
  106.     return(0);
  107. }
  108.  
  109. long symcnt;                /* symbol count */
  110. long tsymlen;                /* total string length */
  111.  
  112. /*
  113.  * rexec
  114.  *    Read the exec structure; ignore any files that don't look
  115.  *    exactly right.
  116.  */
  117. static void
  118. rexec(rfd, wfd)
  119.     register int rfd;
  120.     int wfd;
  121. {
  122.     register RLIB *rp;
  123.     register long nsyms;
  124.     register int nr, symlen;
  125.     register char *strtab, *sym;
  126.     struct exec ebuf;
  127.     struct nlist nl;
  128.     off_t r_off, w_off;
  129.     long strsize;
  130.     void *emalloc();
  131.  
  132.     /* Get current offsets for original and tmp files. */
  133.     r_off = lseek(rfd, (off_t)0, SEEK_CUR);
  134.     w_off = lseek(wfd, (off_t)0, SEEK_CUR);
  135.  
  136.     /* Read in exec structure. */
  137.     nr = read(rfd, (char *)&ebuf, sizeof(struct exec));
  138.     if (nr != sizeof(struct exec))
  139.         goto badread;
  140.  
  141.     /* Check magic number and symbol count. */
  142.     if (N_BADMAG(ebuf) || ebuf.a_syms == 0)
  143.         goto bad1;
  144.  
  145.     /* Seek to string table. */
  146.     if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1)
  147.         error(archive);
  148.  
  149.     /* Read in size of the string table. */
  150.     nr = read(rfd, (char *)&strsize, sizeof(strsize));
  151.     if (nr != sizeof(strsize))
  152.         goto badread;
  153.  
  154.     /* Read in the string table. */
  155.     strsize -= sizeof(strsize);
  156.     strtab = (char *)emalloc(strsize);
  157.     nr = read(rfd, strtab, strsize);
  158.     if (nr != strsize) {
  159. badread:    if (nr < 0)
  160.             error(archive);
  161.         goto bad2;
  162.     }
  163.  
  164.     /* Seek to symbol table. */
  165.     if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1)
  166.         goto bad2;
  167.  
  168.     /* For each symbol read the nlist entry and save it as necessary. */
  169.     nsyms = ebuf.a_syms / sizeof(struct nlist);
  170.     while (nsyms--) {
  171.         if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) {
  172.             if (feof(fp))
  173.                 badfmt();
  174.             error(archive);
  175.         }
  176.  
  177.         /* Ignore if no name or local. */
  178.         if (!nl.n_un.n_strx || !(nl.n_type & N_EXT))
  179.             continue;
  180.  
  181.         /*
  182.          * If the symbol is an undefined external and the n_value
  183.          * field is non-zero, keep it.
  184.          */
  185.         if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value)
  186.             continue;
  187.  
  188.         /* First four bytes are the table size. */
  189.         sym = strtab + nl.n_un.n_strx - sizeof(long);
  190.         symlen = strlen(sym) + 1;
  191.  
  192.         rp = (RLIB *)emalloc(sizeof(RLIB));
  193.         rp->sym = (char *)emalloc(symlen);
  194.         bcopy(sym, rp->sym, symlen);
  195.         rp->symlen = symlen;
  196.         rp->pos = w_off;
  197.  
  198.         /* Build in forward order for "ar -m" command. */
  199.         *pnext = rp;
  200.         pnext = &rp->next;
  201.  
  202.         ++symcnt;
  203.         tsymlen += symlen;
  204.     }
  205.  
  206. bad2:    free(strtab);
  207. bad1:    (void)lseek(rfd, (off_t)r_off, SEEK_SET);
  208. }
  209.  
  210. /*
  211.  * symobj --
  212.  *    Write the symbol table into the archive, computing offsets as
  213.  *    writing.
  214.  */
  215. static void
  216. symobj()
  217. {
  218.     register RLIB *rp;
  219.     struct ranlib rn;
  220.     char hb[sizeof(struct ar_hdr) + 1], pad;
  221.     long ransize, size, stroff;
  222.     gid_t getgid();
  223.     uid_t getuid();
  224.  
  225.     /* Rewind the archive, leaving the magic number. */
  226.     if (fseek(fp, (off_t)SARMAG, SEEK_SET) == (off_t)-1)
  227.         error(archive);
  228.  
  229.     /* Size of the ranlib archive file, pad if necessary. */
  230.     ransize = sizeof(long) +
  231.         symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen;
  232.     if (ransize & 01) {
  233.         ++ransize;
  234.         pad = '\n';
  235.     } else
  236.         pad = '\0';
  237.  
  238.     /* Put out the ranlib archive file header. */
  239. #define    DEFMODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
  240.     (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(),
  241.         DEFMODE & ~umask(0), ransize, ARFMAG);
  242.     if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp))
  243.         error(tname);
  244.  
  245.     /* First long is the size of the ranlib structure section. */
  246.     size = symcnt * sizeof(struct ranlib);
  247.     if (!fwrite((char *)&size, sizeof(size), 1, fp))
  248.         error(tname);
  249.  
  250.     /* Offset of the first archive file. */
  251.     size = SARMAG + sizeof(struct ar_hdr) + ransize;
  252.  
  253.     /*
  254.      * Write out the ranlib structures.  The offset into the string
  255.      * table is cumulative, the offset into the archive is the value
  256.      * set in rexec() plus the offset to the first archive file.
  257.      */
  258.     for (rp = rhead, stroff = 0; rp; rp = rp->next) {
  259.         rn.ran_un.ran_strx = stroff;
  260.         stroff += rp->symlen;
  261.         rn.ran_off = size + rp->pos;
  262.         if (!fwrite((char *)&rn, sizeof(struct ranlib), 1, fp))
  263.             error(archive);
  264.     }
  265.  
  266.     /* Second long is the size of the string table. */
  267.     if (!fwrite((char *)&tsymlen, sizeof(tsymlen), 1, fp))
  268.         error(tname);
  269.  
  270.     /* Write out the string table. */
  271.     for (rp = rhead; rp; rp = rp->next)
  272.         if (!fwrite(rp->sym, rp->symlen, 1, fp))
  273.             error(tname);
  274.  
  275.     if (pad && !fwrite(&pad, sizeof(pad), 1, fp))
  276.         error(tname);
  277.  
  278.     (void)fflush(fp);
  279. }
  280.