1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | #if defined(i3861) || defined(__DGUX__) |
33 | #define PORTAR1 1 |
34 | #endif |
35 | |
36 | #if !defined (COHERENT) && !defined(__COHERENT__) |
37 | #include <ar.h> |
38 | #else |
39 | #include <arcoff.h> |
40 | #endif /* COHERENT, __COHERENT__ */ |
41 | #include "extern.h" |
42 | #include "sysintf.h" |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | #ifndef ASCARCH1 |
49 | #define ASCARCH1 1 /* ASCII time stored in archive */ |
50 | #endif |
51 | |
52 | #ifndef LC1 |
53 | #define LC1 1 /* Turn on library cacheing */ |
54 | #endif |
55 | |
56 | #ifndef CHECKELF1 |
57 | #define CHECKELF1 1 /* Enable Elf long member names */ |
58 | #endif |
59 | |
60 | #ifndef DECODE_ALL_AR_FIELDS0 |
61 | #define DECODE_ALL_AR_FIELDS0 0 /* decode only fields make needs*/ |
62 | #endif |
63 | |
64 | #ifndef AR_TRUNCATE_MEMBER_NAMES0 |
65 | #define AR_TRUNCATE_MEMBER_NAMES0 0 /* truncate member names for */ |
66 | #endif /* comparison. */ |
67 | |
68 | #if LC1 |
69 | # define FOUND_MEMBER0 FALSE0 |
70 | #else |
71 | # define FOUND_MEMBER0 TRUE1 |
72 | # define _cache_member(a, b, c) |
73 | # define _check_cache(a, b, c, d) FALSE0 |
74 | #endif |
75 | |
76 | #define MAXFNAME255 255 /* Max length of member name */ |
77 | #define MAXMNAME8 8 /* Max module name < MAXFNAME */ |
78 | |
79 | |
80 | |
81 | |
82 | struct ar_args { |
83 | char *lib; |
84 | char *member; |
85 | time_t time; |
86 | }; |
87 | |
88 | |
89 | typedef struct AR { |
90 | char ar_name[MAXFNAME255+1]; |
91 | long ar_size; |
92 | time_t ar_time; |
93 | |
94 | #ifdef DOS |
95 | char ar_modname[MAXMNAME8+1]; |
96 | #endif |
97 | |
98 | #if DECODE_ALL_AR_FIELDS0 |
99 | uint16 ar_mode; |
100 | uint16 ar_uid; |
101 | uint16 ar_gid; |
102 | #endif |
103 | } AR, *ARPTR; |
104 | |
105 | |
106 | static int ar_scan ANSI((FILE *,(FILE *, int (*) (FILE *, struct AR *,struct ar_args *), struct ar_args *) |
107 | int (*) ANSI((FILE *, struct AR *,struct ar_args *)),(FILE *, int (*) (FILE *, struct AR *,struct ar_args *), struct ar_args *) |
108 | struct ar_args *))(FILE *, int (*) (FILE *, struct AR *,struct ar_args *), struct ar_args *); |
109 | static int ar_touch ANSI(( FILE *, time_t ))( FILE *, time_t ); |
110 | static int time_function ANSI(( FILE *, struct AR *, struct ar_args * ))( FILE *, struct AR *, struct ar_args * ); |
111 | static int touch_function ANSI(( FILE *, struct AR *, struct ar_args * ))( FILE *, struct AR *, struct ar_args * ); |
112 | static int ar_name_equal ANSI((char *, char *))(char *, char *); |
113 | |
114 | #if LC1 |
115 | static int _cache_member ANSI((char *, char *, time_t))(char *, char *, time_t); |
116 | static int _check_cache ANSI((char *, char *, time_t *, int))(char *, char *, time_t *, int); |
117 | #endif |
118 | |
119 | |
120 | static AR _ar; |
121 | static off_t arhdroffset; |
122 | |
123 | |
124 | PUBLIC time_t |
125 | seek_arch(name, lib) |
126 | |
127 | |
128 | |
129 | |
130 | char *name; |
131 | char *lib; |
132 | { |
133 | FILE *f; |
134 | int rv; |
135 | time_t mtime; |
136 | struct ar_args args; |
137 | |
138 | |
139 | if( _check_cache(name, lib, &mtime, FALSE0) ) return( mtime ); |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | args.lib = lib; |
146 | args.member = name; |
147 | args.time = (time_t)0L; |
148 | |
149 | if( (f = fopen(lib, "r")) == NIL(FILE)((FILE*)((void*)0)) ) return( (time_t)0L ); |
150 | rv = ar_scan(f, time_function, &args ); |
151 | fclose( f ); |
152 | |
153 | if( rv < 0 ) Fatal("(%s): Invalid library format", lib); |
154 | |
155 | return( args.time ); |
156 | } |
157 | |
158 | |
159 | PUBLIC int |
160 | touch_arch(name, lib) |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | char *name; |
167 | char *lib; |
168 | { |
169 | FILE *f; |
170 | int rv; |
171 | struct ar_args args; |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | args.lib = lib; |
178 | args.member = name; |
179 | args.time = (time_t)0L; |
180 | |
181 | if( (f = fopen(lib, "r+")) == NIL(FILE)((FILE*)((void*)0)) ) return( (time_t)1L ); |
182 | rv = ar_scan(f, touch_function, &args ); |
183 | fclose( f ); |
184 | |
185 | if( rv < 0 ) Fatal("(%s): Invalid library format", lib); |
186 | |
187 | return( 0 ); |
188 | } |
189 | |
190 | |
191 | |
192 | static int |
193 | time_function(f, arp, argp) |
194 | |
195 | |
196 | |
197 | FILE *f; |
198 | struct AR *arp; |
199 | struct ar_args *argp; |
200 | { |
201 | int rv = _cache_member( arp->ar_name, argp->lib, arp->ar_time ); |
202 | |
203 | if( ar_name_equal (argp->member, arp->ar_name)) { |
204 | argp->time = arp->ar_time; |
205 | |
206 | if( arp->ar_time == 0 && !(Glob_attr & A_SILENT0x00002) ) |
207 | Warning( "(%s): Can't extract library member timestamp; using EPOCH", |
208 | argp->member); |
209 | |
210 | return( rv ); |
211 | } |
212 | |
213 | return( FALSE0 ); |
214 | } |
215 | |
216 | |
217 | |
218 | static int |
219 | touch_function(f, arp, argp) |
220 | |
221 | |
222 | |
223 | FILE *f; |
224 | struct AR *arp; |
225 | struct ar_args *argp; |
226 | { |
227 | extern time_t time ANSI(( time_t * ))( time_t * ); |
228 | time_t now = time((time_t*) NULL((void*)0)); |
229 | |
230 | if( ar_name_equal(argp->member, arp->ar_name) ) { |
231 | _check_cache( argp->member, argp->lib, &now, TRUE1 ); |
232 | ar_touch(f, now ); |
233 | |
234 | return( TRUE1 ); |
235 | } |
236 | |
237 | return( FALSE0 ); |
238 | } |
239 | |
240 | |
241 | static int |
242 | ar_name_equal (char * name1, char * name2) |
243 | { |
244 | int equal; |
245 | |
246 | #if AR_TRUNCATE_MEMBER_NAMES0 |
247 | struct ar_hdr hdr; |
248 | |
249 | equal = !strncmp (name1, name2, sizeof (hdr.ar_name)-1); |
250 | #else |
251 | equal = !strcmp (name1, name2); |
252 | #endif |
253 | |
254 | return equal; |
255 | } |
256 | |
257 | |
258 | static int |
259 | ar_scan(f, function, arg) |
260 | |
261 | |
262 | |
263 | |
264 | |
265 | |
266 | |
267 | |
268 | register FILE *f; |
269 | int (*function) ANSI((FILE *, struct AR *, struct ar_args *))(FILE *, struct AR *, struct ar_args *); |
270 | struct ar_args *arg; |
271 | { |
272 | extern long atol (); |
273 | register char *p; |
274 | struct ar_hdr arhdr; |
275 | long nsize; |
276 | long arind=0; |
277 | int process; |
278 | #if defined(_AIX) |
279 | struct fl_hdr flhdr; |
280 | char magic[SAIAMAG]; |
281 | #else |
282 | #if ASCARCH1 |
283 | char magic[SARMAG8]; |
284 | #else |
285 | unsigned short word; |
286 | #endif |
287 | #endif |
288 | |
289 | fseek( f, 0L, 0 ); |
290 | |
291 | #if ASCARCH1 |
292 | #if defined(_AIX) |
293 | if( fread( (char *)&flhdr, sizeof(flhdr), 1, f ) != 1 ) return (-1); |
294 | if( strncmp(flhdr.fl_magic,AIAMAG, SAIAMAG) != 0 ) return(-1); |
295 | fseek(f, atol(flhdr.fl_fstmoff), 0 ); |
296 | #else |
297 | if( fread( magic, sizeof(magic), 1, f ) != 1 ) return( -1 ); |
298 | if( strncmp(magic, ARMAG"!<arch>\n", SARMAG8) != 0 ) return( -1 ); |
299 | #endif |
300 | #else |
301 | if( fread( (char*)&word, sizeof(word), 1, f ) != 1 ) return( -1 ); |
302 | if( word != ARMAG"!<arch>\n" ) return( -1 ); |
303 | #endif |
304 | |
305 | |
306 | |
307 | while( 1 ) { |
308 | arhdroffset = ftell(f); |
309 | #if defined(_AIX) |
310 | if( fread((char*)&arhdr,sizeof(arhdr)-sizeof(arhdr._ar_name),1,f)!=1) |
311 | break; |
312 | nsize = atoi(arhdr.ar_namlen); |
313 | fseek(f, arhdroffset+(unsigned long)(((struct ar_hdr *)0)->_ar_name.ar_name), 0); |
314 | if( fread((char*)_ar.ar_name,nsize,1,f)!=1) |
315 | break; |
316 | _ar.ar_name[nsize]='\0'; |
317 | #else |
318 | if( fread((char*) &arhdr, sizeof(arhdr), 1, f) != 1 ) break; |
319 | strncpy(_ar.ar_name, arhdr.ar_name, nsize = sizeof(arhdr.ar_name)); |
320 | #endif |
321 | |
322 | for( p = &_ar.ar_name[nsize]; |
323 | --p >= _ar.ar_name && *p == ' ';); |
324 | |
325 | p[1] = '\0'; |
326 | if( *p == '/' ) *p = 0; |
327 | |
328 | |
329 | |
330 | #if CHECKELF1 |
331 | if( _ar.ar_name[0] == '/' && _ar.ar_name[1] == '\0' ) { |
332 | arind = arhdroffset+sizeof(arhdr); |
333 | process = 0; |
334 | } |
335 | else |
336 | #endif |
337 | process = 1; |
338 | |
339 | #if !defined(_AIX) |
340 | #if ASCARCH1 |
341 | if( strncmp(arhdr.ar_fmag, ARFMAG"`\n", sizeof(arhdr.ar_fmag)) != 0 ) |
342 | return( -1 ); |
343 | _ar.ar_time = atol(arhdr.ar_date); |
344 | _ar.ar_size = atol(arhdr.ar_size); |
345 | #else |
346 | _ar.ar_time = arhdr.ar_date; |
347 | _ar.ar_size = arhdr.ar_size; |
348 | #endif |
349 | #if CHECKELF1 |
350 | |
351 | |
352 | if(arind && _ar.ar_name[0] == '/') { |
353 | long offset = atol(_ar.ar_name+1); |
354 | long here = ftell(f); |
355 | int c; |
356 | |
357 | fseek(f, arind+offset, 0); |
358 | p = _ar.ar_name; |
359 | while((c=fgetc(f)) != EOF(-1)) { |
360 | *p++ = c; |
361 | if(c == '/') { |
362 | p[-1] = '\0'; |
363 | break; |
364 | } |
365 | } |
366 | |
367 | if (c==EOF(-1)) return(-1); |
368 | fseek(f, here, 0); |
369 | } |
370 | #endif |
371 | #else |
372 | #if ASCARCH1 |
373 | _ar.ar_time = atol(arhdr.ar_date); |
374 | _ar.ar_size = atol(arhdr.ar_nxtmem); |
375 | #else |
376 | _ar.ar_time = arhdr.ar_date; |
377 | _ar.ar_size = arhdr.ar_nxtmem; |
378 | #endif |
379 | #endif |
380 | |
381 | |
382 | #if DECODE_ALL_AR_FIELDS0 |
383 | #if ASCARCH1 |
384 | _ar.ar_mode = atoi(arhdr.ar_mode); |
385 | _ar.ar_uid = atoi(arhdr.ar_uid); |
386 | _ar.ar_gid = atoi(arhdr.ar_gid); |
387 | #else |
388 | _ar.ar_mode = arhdr.ar_mode; |
389 | _ar.ar_uid = arhdr.ar_uid; |
390 | _ar.ar_gid = arhdr.ar_gid; |
391 | #endif |
392 | #endif |
393 | if( process && (*function)(f, &_ar, arg) ) return( 1 ); |
394 | |
395 | #if defined(_AIX) |
396 | if( _ar.ar_size == 0L ) break; |
397 | fseek( f, (long) _ar.ar_size, 0 ); |
398 | #else |
399 | fseek( f, arhdroffset + sizeof(arhdr) + ((_ar.ar_size+1) & ~1L), 0 ); |
400 | #endif |
401 | } |
402 | |
403 | #if !defined(_AIX) |
404 | if( !feof(f) ) return( -1 ); |
405 | #endif |
406 | return 0; |
407 | } |
408 | |
409 | |
410 | |
411 | static int |
412 | ar_touch( f, now ) |
413 | |
414 | |
415 | FILE *f; |
416 | time_t now; |
417 | { |
418 | |
419 | fseek(f, arhdroffset + (unsigned long)(((struct ar_hdr *)0)->ar_date), 0); |
420 | |
421 | #if ASCARCH1 |
422 | fprintf(f, "%lu", now); |
423 | #else |
424 | fwrite((char *)now, sizeof(now), 1, f); |
425 | #endif |
426 | |
427 | return( ferror(f) ? 0 : 1 ); |
428 | } |
429 | |
430 | |
431 | #if LC1 |
432 | typedef struct mem { |
433 | time_t m_time; |
434 | struct mem *m_next; |
435 | char m_valid; |
436 | char m_name[1]; |
437 | } MEM, *MEMPTR; |
438 | |
439 | typedef struct lib { |
440 | struct lib *lb_next; |
441 | struct mem *lb_members; |
442 | char lb_valid; |
443 | char *lb_name; |
444 | } LIB, *LIBPTR; |
445 | |
446 | static LIBPTR _cache = NIL(LIB)((LIB*)((void*)0)); |
447 | static MEMPTR _find_member ANSI(( LIBPTR, char * ))( LIBPTR, char * ); |
448 | |
449 | static int |
450 | _check_cache( name, lib, pmtime, touch ) |
451 | |
452 | |
453 | |
454 | |
455 | char *name; |
456 | char *lib; |
457 | time_t *pmtime; |
458 | int touch; |
459 | { |
460 | register MEMPTR mp; |
461 | register LIBPTR lp; |
462 | |
463 | for( lp=_cache; lp != NIL(LIB)((LIB*)((void*)0)) && lp->lb_name != lib; lp=lp->lb_next ); |
464 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) return( FALSE0 ); |
465 | |
466 | mp = _find_member( lp, name ); |
467 | if( mp == NIL(MEM)((MEM*)((void*)0)) || !mp->m_valid ) return( FALSE0 ); |
468 | |
469 | if( touch == TRUE1 ) |
470 | { |
471 | mp->m_time = *pmtime; |
472 | mp->m_valid = 1; |
473 | } |
474 | else |
475 | *pmtime = mp->m_time; |
476 | |
477 | lp->lb_valid = 1; |
478 | lp->lb_members = mp; |
479 | |
480 | return( TRUE1 ); |
481 | } |
482 | |
483 | |
484 | |
485 | static int |
486 | _cache_member( name, lib, mtime ) |
487 | |
488 | |
489 | char *name; |
490 | char *lib; |
491 | time_t mtime; |
492 | { |
493 | register MEMPTR mp; |
494 | register LIBPTR lp; |
495 | |
496 | for( lp=_cache; |
497 | lp != NIL(LIB)((LIB*)((void*)0)) && lp->lb_name != NIL(char)((char*)((void*)0)) && lp->lb_name != lib; |
| 1 | Assuming 'lp' is equal to null | |
|
498 | lp=lp->lb_next); |
499 | |
500 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) |
| |
501 | { |
502 | lp = (LIBPTR) malloc(sizeof(LIB)); |
| |
503 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) No_ram(); |
| 4 | | Assuming 'lp' is equal to null | |
|
| |
504 | |
505 | lp->lb_name = lib; |
| 6 | | Access to field 'lb_name' results in a dereference of a null pointer (loaded from variable 'lp') |
|
506 | lp->lb_members = NIL(MEM)((MEM*)((void*)0)); |
507 | lp->lb_next = _cache; |
508 | lp->lb_valid = 0; |
509 | _cache = lp; |
510 | } |
511 | |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | mp = NIL(MEM)((MEM*)((void*)0)); |
518 | |
519 | if( mp == NIL(MEM)((MEM*)((void*)0)) ) |
520 | { |
521 | mp = (MEMPTR) malloc(sizeof(char)*offsetof(MEM,m_name[strlen(name)+1])__builtin_offsetof(MEM, m_name[strlen(name)+1])); |
522 | if( mp == NIL(MEM)((MEM*)((void*)0)) ) No_ram(); |
523 | |
524 | strcpy( mp->m_name, name ); |
525 | mp->m_time = mtime; |
526 | |
527 | if( lp->lb_members == NIL(MEM)((MEM*)((void*)0)) ) { |
528 | mp->m_next = mp; |
529 | lp->lb_members = mp; |
530 | } |
531 | else { |
532 | mp->m_next = lp->lb_members->m_next; |
533 | lp->lb_members->m_next = mp; |
534 | lp->lb_members = mp; |
535 | } |
536 | } |
537 | else |
538 | mp->m_time = mtime; |
539 | |
540 | mp->m_valid = 1; |
541 | |
542 | return( lp->lb_valid ); |
543 | } |
544 | |
545 | |
546 | static MEMPTR |
547 | _find_member( lp, name ) |
548 | LIBPTR lp; |
549 | char *name; |
550 | { |
551 | register MEMPTR mp = lp->lb_members; |
552 | |
553 | if( mp == NIL(MEM)((MEM*)((void*)0)) ) return(mp); |
554 | |
555 | do { |
556 | if( !strcmp(mp->m_name, name ) ) return( mp ); |
557 | mp = mp->m_next; |
558 | } |
559 | while( mp != lp->lb_members ); |
560 | |
561 | return( NIL(MEM)((MEM*)((void*)0)) ); |
562 | } |
563 | #endif |
564 | |
565 | |
566 | |
567 | PUBLIC void |
568 | void_lcache( lib, member ) |
569 | |
570 | |
571 | |
572 | |
573 | char *lib; |
574 | char *member; |
575 | { |
576 | #if LC1 |
577 | register LIBPTR lp; |
578 | register MEMPTR mp; |
579 | register MEMPTR tmp; |
580 | |
581 | for( lp=_cache; lp != NIL(LIB)((LIB*)((void*)0)) && lp->lb_name != lib; lp=lp->lb_next ); |
582 | if( lp == NIL(LIB)((LIB*)((void*)0)) ) return; |
583 | |
584 | if( member == NIL(char)((char*)((void*)0)) ) { |
585 | mp = lp->lb_members; |
586 | do { |
587 | tmp = mp->m_next; |
588 | (void) free( mp ); |
589 | mp = tmp; |
590 | } while( mp != lp->lb_members ); |
591 | |
592 | lp->lb_valid = 0; |
593 | lp->lb_members = NIL(MEM)((MEM*)((void*)0)); |
594 | lp->lb_name = NIL(char)((char*)((void*)0)); |
595 | } |
596 | else { |
597 | mp=lp->lb_members; |
598 | do { |
599 | if( strcmp( member, mp->m_name) == 0 ) { |
600 | lp->lb_members = mp->m_next; |
601 | mp->m_valid = 0; |
602 | } |
603 | |
604 | mp=mp->m_next; |
605 | } while( mp != lp->lb_members ); |
606 | } |
607 | #endif |
608 | } |