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.3 (Berkeley) 01/22/86"; 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 3000 34 int tnum; 35 #define STRTABSZ 30000 36 int tssiz; 37 char *strtab; 38 int ssiz; 39 int new; 40 char tempnm[] = "__.SYMDEF"; 41 char firstname[17]; 42 void stash(); 43 char *malloc(), *calloc(); 44 45 /* 46 * table segment definitions 47 */ 48 char *segalloc(); 49 void segclean(); 50 struct tabsegment { 51 struct tabsegment *pnext; 52 unsigned nelem; 53 struct ranlib tab[TABSZ]; 54 } tabbase, *ptabseg; 55 struct strsegment { 56 struct strsegment *pnext; 57 unsigned nelem; 58 char stab[STRTABSZ]; 59 } strbase, *pstrseg; 60 61 main(argc, argv) 62 char **argv; 63 { 64 char cmdbuf[BUFSIZ]; 65 /* magbuf must be an int array so it is aligned on an int-ish 66 boundary, so that we may access its first word as an int! */ 67 int magbuf[(SARMAG+sizeof(int))/sizeof(int)]; 68 register int just_touch = 0; 69 register struct tabsegment *ptab; 70 register struct strsegment *pstr; 71 72 /* check for the "-t" flag" */ 73 if (argc > 1 && strcmp(argv[1], "-t") == 0) { 74 just_touch++; 75 argc--; 76 argv++; 77 } 78 79 --argc; 80 while(argc--) { 81 fi = fopen(*++argv,"r"); 82 if (fi == NULL) { 83 fprintf(stderr, "ranlib: cannot open %s\n", *argv); 84 continue; 85 } 86 off = SARMAG; 87 fread((char *)magbuf, 1, SARMAG, fi); 88 if (strncmp((char *)magbuf, ARMAG, SARMAG)) { 89 if (magbuf[0] == OARMAG) 90 fprintf(stderr, "old format "); 91 else 92 fprintf(stderr, "not an "); 93 fprintf(stderr, "archive: %s\n", *argv); 94 continue; 95 } 96 if (just_touch) { 97 register int len; 98 99 fseek(fi, (long) SARMAG, 0); 100 if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) { 101 fprintf(stderr, "malformed archive: %s\n", 102 *argv); 103 continue; 104 } 105 len = strlen(tempnm); 106 if (bcmp(cmdbuf, tempnm, len) != 0 || 107 cmdbuf[len] != ' ') { 108 fprintf(stderr, "no symbol table: %s\n", *argv); 109 continue; 110 } 111 fclose(fi); 112 fixdate(*argv); 113 continue; 114 } 115 fseek(fi, 0L, 0); 116 new = tssiz = tnum = 0; 117 segclean(); 118 if (nextel(fi) == 0) { 119 fclose(fi); 120 continue; 121 } 122 do { 123 long o; 124 register n; 125 struct nlist sym; 126 127 fread((char *)&exp, 1, sizeof(struct exec), fi); 128 if (N_BADMAG(exp)) 129 continue; 130 if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name))) 131 continue; 132 if (exp.a_syms == 0) { 133 fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name); 134 continue; 135 } 136 o = N_STROFF(exp) - sizeof (struct exec); 137 if (ftell(fi)+o+sizeof(ssiz) >= off) { 138 fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name); 139 continue; 140 } 141 fseek(fi, o, 1); 142 fread((char *)&ssiz, 1, sizeof (ssiz), fi); 143 if (ssiz < sizeof ssiz){ 144 /* sanity check */ 145 fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name); 146 continue; 147 } 148 strtab = (char *)calloc(1, ssiz); 149 if (strtab == 0) { 150 fprintf(stderr, "ranlib: ran out of memory\n"); 151 exit(1); 152 } 153 fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi); 154 fseek(fi, -(exp.a_syms+ssiz), 1); 155 n = exp.a_syms / sizeof(struct nlist); 156 while (--n >= 0) { 157 fread((char *)&sym, 1, sizeof(sym), fi); 158 if (sym.n_un.n_strx == 0) 159 continue; 160 sym.n_un.n_name = strtab + sym.n_un.n_strx; 161 if ((sym.n_type&N_EXT)==0) 162 continue; 163 switch (sym.n_type&N_TYPE) { 164 165 case N_UNDF: 166 if (sym.n_value!=0) 167 stash(&sym); 168 continue; 169 170 default: 171 stash(&sym); 172 continue; 173 } 174 } 175 free(strtab); 176 } while(nextel(fi)); 177 new = fixsize(); 178 fclose(fi); 179 fo = fopen(tempnm, "w"); 180 if(fo == NULL) { 181 fprintf(stderr, "can't create temporary\n"); 182 exit(1); 183 } 184 tnum *= sizeof (struct ranlib); 185 fwrite(&tnum, 1, sizeof (tnum), fo); 186 tnum /= sizeof (struct ranlib); 187 ptab = &tabbase; 188 do { 189 fwrite((char *)ptab->tab, ptab->nelem, 190 sizeof(struct ranlib), fo); 191 } while (ptab = ptab->pnext); 192 fwrite(&tssiz, 1, sizeof (tssiz), fo); 193 pstr = &strbase; 194 do { 195 fwrite(pstr->stab, pstr->nelem, 1, fo); 196 tssiz -= pstr->nelem; 197 } while (pstr = pstr->pnext); 198 /* pad with nulls */ 199 while (tssiz--) putc('\0', fo); 200 fclose(fo); 201 if(new) 202 sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm); 203 else 204 sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm); 205 if(system(cmdbuf)) 206 fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf); 207 else 208 fixdate(*argv); 209 unlink(tempnm); 210 } 211 exit(0); 212 } 213 214 nextel(af) 215 FILE *af; 216 { 217 register r; 218 register char *cp; 219 220 oldoff = off; 221 fseek(af, off, 0); 222 r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 223 if (r != sizeof(struct ar_hdr)) 224 return(0); 225 for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 226 if (*cp == ' ') 227 *cp = '\0'; 228 arsize = atol(archdr.ar_size); 229 if (arsize & 1) 230 arsize++; 231 off = ftell(af) + arsize; 232 return(1); 233 } 234 235 void 236 stash(s) 237 struct nlist *s; 238 { 239 register char *cp; 240 register char *strtab; 241 register strsiz; 242 register struct ranlib *tab; 243 register tabsiz; 244 245 if (ptabseg->nelem >= TABSZ) { 246 /* allocate a new symbol table segment */ 247 ptabseg = ptabseg->pnext = 248 (struct tabsegment *) segalloc(sizeof(struct tabsegment)); 249 ptabseg->pnext = NULL; 250 ptabseg->nelem = 0; 251 } 252 tabsiz = ptabseg->nelem; 253 tab = ptabseg->tab; 254 255 if (pstrseg->nelem >= STRTABSZ) { 256 /* allocate a new string table segment */ 257 pstrseg = pstrseg->pnext = 258 (struct strsegment *) segalloc(sizeof(struct strsegment)); 259 pstrseg->pnext = NULL; 260 pstrseg->nelem = 0; 261 } 262 strsiz = pstrseg->nelem; 263 strtab = pstrseg->stab; 264 265 tab[tabsiz].ran_un.ran_strx = tssiz; 266 tab[tabsiz].ran_off = oldoff; 267 redo: 268 for (cp = s->n_un.n_name; strtab[strsiz++] = *cp++;) 269 if (strsiz >= STRTABSZ) { 270 /* allocate a new string table segment */ 271 pstrseg = pstrseg->pnext = 272 (struct strsegment *) segalloc(sizeof(struct strsegment)); 273 pstrseg->pnext = NULL; 274 strsiz = pstrseg->nelem = 0; 275 strtab = pstrseg->stab; 276 goto redo; 277 } 278 279 tssiz += strsiz - pstrseg->nelem; /* length of the string */ 280 pstrseg->nelem = strsiz; 281 tnum++; 282 ptabseg->nelem++; 283 } 284 285 /* allocate a zero filled segment of size bytes */ 286 char * 287 segalloc(size) 288 unsigned size; 289 { 290 char *pseg = NULL; 291 292 pseg = malloc(size); 293 if (pseg == NULL) { 294 fprintf(stderr, "ranlib: ran out of memeory\n"); 295 exit(1); 296 } 297 return(pseg); 298 } 299 300 /* free segments */ 301 void 302 segclean() 303 { 304 register struct tabsegment *ptab; 305 register struct strsegment *pstr; 306 307 /* 308 * symbol table 309 * 310 * The first entry is static. 311 */ 312 ptabseg = &tabbase; 313 ptab = ptabseg->pnext; 314 while (ptabseg = ptab) { 315 ptab = ptabseg->pnext; 316 free((char *)ptabseg); 317 } 318 ptabseg = &tabbase; 319 ptabseg->pnext = NULL; 320 ptabseg->nelem = 0; 321 322 /* 323 * string table 324 * 325 * The first entry is static. 326 */ 327 pstrseg = &strbase; 328 pstr = pstrseg->pnext; 329 while (pstrseg = pstr) { 330 pstr = pstrseg->pnext; 331 free((char *)pstrseg); 332 } 333 pstrseg = &strbase; 334 pstrseg->pnext = NULL; 335 pstrseg->nelem = 0; 336 } 337 338 fixsize() 339 { 340 int i; 341 off_t offdelta; 342 register struct tabsegment *ptab; 343 344 if (tssiz&1) 345 tssiz++; 346 offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) + 347 sizeof (tssiz) + tssiz; 348 off = SARMAG; 349 nextel(fi); 350 if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) { 351 new = 0; 352 offdelta -= sizeof(archdr) + arsize; 353 } else { 354 new = 1; 355 strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name)); 356 } 357 ptab = &tabbase; 358 do { 359 for (i = 0; i < ptab->nelem; i++) 360 ptab->tab[i].ran_off += offdelta; 361 } while (ptab = ptab->pnext); 362 return(new); 363 } 364 365 /* patch time */ 366 fixdate(s) 367 char *s; 368 { 369 long time(); 370 char buf[24]; 371 int fd; 372 373 fd = open(s, 1); 374 if(fd < 0) { 375 fprintf(stderr, "ranlib: can't reopen %s\n", s); 376 return; 377 } 378 sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); 379 lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0); 380 write(fd, buf, sizeof(archdr.ar_date)); 381 close(fd); 382 } 383