1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)ranlib.c 5.1 (Berkeley) 06/06/85"; 15 #endif not lint 16 17 /* 18 * ranlib - create table of contents for archive; string table version 19 */ 20 #include <sys/types.h> 21 #include <ar.h> 22 #include <ranlib.h> 23 #include <a.out.h> 24 #include <stdio.h> 25 26 struct ar_hdr archdr; 27 #define OARMAG 0177545 28 long arsize; 29 struct exec exp; 30 FILE *fi, *fo; 31 long off, oldoff; 32 long atol(), ftell(); 33 #define TABSZ 6000 34 struct ranlib tab[TABSZ]; 35 int tnum; 36 #define STRTABSZ 75000 37 char tstrtab[STRTABSZ]; 38 int tssiz; 39 char *strtab; 40 int ssiz; 41 int new; 42 char tempnm[] = "__.SYMDEF"; 43 char firstname[17]; 44 45 main(argc, argv) 46 char **argv; 47 { 48 char cmdbuf[BUFSIZ]; 49 /* magbuf must be an int array so it is aligned on an int-ish 50 boundary, so that we may access its first word as an int! */ 51 int magbuf[(SARMAG+sizeof(int))/sizeof(int)]; 52 register int just_touch = 0; 53 54 /* check for the "-t" flag" */ 55 if (argc > 1 && strcmp(argv[1], "-t") == 0) { 56 just_touch++; 57 argc--; 58 argv++; 59 } 60 61 --argc; 62 while(argc--) { 63 fi = fopen(*++argv,"r"); 64 if (fi == NULL) { 65 fprintf(stderr, "ranlib: cannot open %s\n", *argv); 66 continue; 67 } 68 off = SARMAG; 69 fread((char *)magbuf, 1, SARMAG, fi); 70 if (strncmp((char *)magbuf, ARMAG, SARMAG)) { 71 if (magbuf[0] == OARMAG) 72 fprintf(stderr, "old format "); 73 else 74 fprintf(stderr, "not an "); 75 fprintf(stderr, "archive: %s\n", *argv); 76 continue; 77 } 78 if (just_touch) { 79 register int len; 80 81 fseek(fi, (long) SARMAG, 0); 82 if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) { 83 fprintf(stderr, "malformed archive: %s\n", 84 *argv); 85 continue; 86 } 87 len = strlen(tempnm); 88 if (bcmp(cmdbuf, tempnm, len) != 0 || 89 cmdbuf[len] != ' ') { 90 fprintf(stderr, "no symbol table: %s\n", *argv); 91 continue; 92 } 93 fclose(fi); 94 fixdate(*++argv); 95 continue; 96 } 97 fseek(fi, 0L, 0); 98 new = tnum = 0; 99 if (nextel(fi) == 0) { 100 fclose(fi); 101 continue; 102 } 103 do { 104 long o; 105 register n; 106 struct nlist sym; 107 108 fread((char *)&exp, 1, sizeof(struct exec), fi); 109 if (N_BADMAG(exp)) 110 continue; 111 if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name))) 112 continue; 113 if (exp.a_syms == 0) { 114 fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name); 115 continue; 116 } 117 o = N_STROFF(exp) - sizeof (struct exec); 118 if (ftell(fi)+o+sizeof(ssiz) >= off) { 119 fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name); 120 continue; 121 } 122 fseek(fi, o, 1); 123 fread((char *)&ssiz, 1, sizeof (ssiz), fi); 124 if (ssiz < sizeof ssiz){ 125 /* sanity check */ 126 fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name); 127 continue; 128 } 129 strtab = (char *)calloc(1, ssiz); 130 if (strtab == 0) { 131 fprintf(stderr, "ranlib: ran out of memory\n"); 132 exit(1); 133 } 134 fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi); 135 fseek(fi, -(exp.a_syms+ssiz), 1); 136 n = exp.a_syms / sizeof(struct nlist); 137 while (--n >= 0) { 138 fread((char *)&sym, 1, sizeof(sym), fi); 139 if (sym.n_un.n_strx == 0) 140 continue; 141 sym.n_un.n_name = strtab + sym.n_un.n_strx; 142 if ((sym.n_type&N_EXT)==0) 143 continue; 144 switch (sym.n_type&N_TYPE) { 145 146 case N_UNDF: 147 if (sym.n_value!=0) 148 stash(&sym); 149 continue; 150 151 default: 152 stash(&sym); 153 continue; 154 } 155 } 156 } while(nextel(fi)); 157 new = fixsize(); 158 fclose(fi); 159 fo = fopen(tempnm, "w"); 160 if(fo == NULL) { 161 fprintf(stderr, "can't create temporary\n"); 162 exit(1); 163 } 164 tnum *= sizeof (struct ranlib); 165 fwrite(&tnum, 1, sizeof (tnum), fo); 166 tnum /= sizeof (struct ranlib); 167 fwrite((char *)tab, tnum, sizeof(struct ranlib), fo); 168 fwrite(&tssiz, 1, sizeof (tssiz), fo); 169 fwrite(tstrtab, tssiz, 1, fo); 170 fclose(fo); 171 if(new) 172 sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm); 173 else 174 sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm); 175 if(system(cmdbuf)) 176 fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf); 177 else 178 fixdate(*argv); 179 unlink(tempnm); 180 } 181 exit(0); 182 } 183 184 nextel(af) 185 FILE *af; 186 { 187 register r; 188 register char *cp; 189 190 oldoff = off; 191 fseek(af, off, 0); 192 r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 193 if (r != sizeof(struct ar_hdr)) 194 return(0); 195 for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 196 if (*cp == ' ') 197 *cp = '\0'; 198 arsize = atol(archdr.ar_size); 199 if (arsize & 1) 200 arsize++; 201 off = ftell(af) + arsize; 202 return(1); 203 } 204 205 stash(s) 206 struct nlist *s; 207 { 208 int i; 209 register char *cp; 210 211 if(tnum >= TABSZ) { 212 fprintf(stderr, "ranlib: symbol table overflow\n"); 213 exit(1); 214 } 215 tab[tnum].ran_un.ran_strx = tssiz; 216 tab[tnum].ran_off = oldoff; 217 for (cp = s->n_un.n_name; tstrtab[tssiz++] = *cp++;) 218 if (tssiz > STRTABSZ) { 219 fprintf(stderr, "ranlib: string table overflow\n"); 220 exit(1); 221 } 222 tnum++; 223 } 224 225 fixsize() 226 { 227 int i; 228 off_t offdelta; 229 230 if (tssiz&1) 231 tssiz++; 232 offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) + 233 sizeof (tssiz) + tssiz; 234 off = SARMAG; 235 nextel(fi); 236 if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) { 237 new = 0; 238 offdelta -= sizeof(archdr) + arsize; 239 } else { 240 new = 1; 241 strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name)); 242 } 243 for(i=0; i<tnum; i++) 244 tab[i].ran_off += offdelta; 245 return(new); 246 } 247 248 /* patch time */ 249 fixdate(s) 250 char *s; 251 { 252 long time(); 253 char buf[24]; 254 int fd; 255 256 fd = open(s, 1); 257 if(fd < 0) { 258 fprintf(stderr, "ranlib: can't reopen %s\n", s); 259 return; 260 } 261 sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); 262 lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0); 263 write(fd, buf, sizeof(archdr.ar_date)); 264 close(fd); 265 } 266