2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 /* ar - archiver Author: Michiel Huisjes */
6 /* Made into arch/aal by Ceriel Jacobs
9 static char RcsId
[] = "$Header$";
12 * Usage: [arch|aal] [adprtvx] archive [file] ...
16 * r: replace (append when not in archive)
18 * t: print contents of archive
19 * p: print named files
20 * l: temporaries in current directory instead of /usr/tmp
21 * c: don't give "create" message
22 * u: replace only if dated later than member in archive
24 * D: make distribution: use distr_time, uid=2, gid=2, mode=0644
28 #include <sys/types.h>
31 #define S_IREAD S_IRUSR
34 #define S_IWRITE S_IWUSR
37 #define S_IEXEC S_IXUSR
44 #define MAGIC_NUMBER AALMAG
47 unsigned int tnum
= 0;
49 unsigned int tssiz
= 0;
50 char *malloc(), *realloc(), *strcpy(), *strncpy();
52 unsigned int tabsz
, strtabsz
;
54 #define MAGIC_NUMBER ARMAG
58 #define odd(nr) (nr & 01)
59 #define even(nr) (odd(nr) ? nr + 1 : nr)
69 #define MEMBER struct ar_hdr
71 #define NIL_PTR ((char *) 0)
72 #define NIL_MEM ((MEMBER *) 0)
73 #define NIL_LONG ((long *) 0)
75 #define IO_SIZE (10 * 1024)
77 #define equal(str1, str2) (!strncmp((str1), (str2), 14))
79 #define S_ISDIR(m) (m & S_IFDIR) /* is a directory */
99 char io_buffer
[IO_SIZE
];
104 char *temp_arch
= &temp_buf
[0];
105 extern char *mktemp();
106 extern char *ctime();
110 error(TRUE
, "usage: %s %s archive [file] ...\n",
121 error(quit
, str1
, str2
, str3
, str4
)
123 char *str1
, *str2
, *str3
, *str4
;
127 sprint(errbuf
, str1
, str2
, str3
, str4
);
128 write(2, errbuf
, strlen(errbuf
));
138 register char *ptr
= path
;
139 register char *last
= NIL_PTR
;
141 while (*ptr
!= '\0') {
148 if (*(last
+ 1) == '\0') {
150 return basename(path
);
155 extern unsigned int rd_unsigned2();
157 open_archive(name
, mode
)
161 unsigned short magic
= 0;
164 if (mode
== CREATE
) {
165 if ((fd
= creat(name
, 0666)) < 0)
166 error(TRUE
, "cannot creat %s\n", name
);
167 magic
= MAGIC_NUMBER
;
172 if ((fd
= open(name
, mode
)) < 0) {
173 if (mode
== APPEND
) {
174 close(open_archive(name
, CREATE
));
175 if (!nocr_fl
) error(FALSE
, "%s: creating %s\n", progname
, name
);
176 return open_archive(name
, APPEND
);
178 error(TRUE
, "cannot open %s\n", name
);
181 magic
= rd_unsigned2(fd
);
182 if (magic
!= AALMAG
&& magic
!= ARMAG
)
183 error(TRUE
, "%s is not in ar format\n", name
);
210 for (ptr
= argv
[1]; *ptr
; ptr
++) {
258 if (needs_arg
&& argc
<= 3)
264 stat(progname
, &statbuf
);
265 distr_time
= statbuf
.st_mtime
;
268 if (local_fl
) strcpy(temp_arch
, "ar.XXXXXX");
269 else strcpy(temp_arch
, "/usr/tmp/ar.XXXXXX");
271 if (app_fl
+ ex_fl
+ del_fl
+ rep_fl
+ show_fl
+ pr_fl
!= 1)
274 if (update_fl
&& !rep_fl
)
285 tab
= (struct ranlib
*) malloc(512 * sizeof(struct ranlib
));
286 tstrtab
= malloc(4096);
287 if (!tab
|| !tstrtab
) error(TRUE
,"Out of core\n");
292 signal(SIGINT
, catch);
301 static MEMBER member
;
304 if (rd_arhdr(ar_fd
, &member
) == 0)
306 if (member
.ar_size
< 0) {
307 error(TRUE
, "archive has member with negative size\n");
310 if (equal(SYMDEF
, member
.ar_name
)) {
311 lseek(ar_fd
, member
.ar_size
, 1);
322 register char *argv
[];
324 register MEMBER
*member
;
326 int temp_fd
, read_chars
;
328 ar_fd
= open_archive(argv
[2], (show_fl
|| pr_fl
|| ex_fl
) ? READ
: APPEND
);
334 temp_fd
= open_archive(temp_arch
, CREATE
);
335 while ((member
= get_member()) != NIL_MEM
) {
337 for (i
= 3; i
< argc
; i
++) {
338 if (equal(basename(argv
[i
]), member
->ar_name
))
341 if (i
== argc
|| app_fl
) {
349 print("%s: already in archive\n", argv
[i
]);
353 wr_arhdr(temp_fd
, member
);
354 copy_member(member
, ar_fd
, temp_fd
, 0);
358 if (app_fl
&& i
!= argc
) {
359 print("%s: already in archive\n", argv
[i
]);
363 lseek(ar_fd
, even(member
->ar_size
),1);
375 if (stat(argv
[i
], &status
) >= 0) {
376 if(status
.st_mtime
<= member
->ar_date
)
381 add(argv
[i
], temp_fd
, "r - %s\n");
383 wr_arhdr(temp_fd
, member
);
384 copy_member(member
, ar_fd
, temp_fd
, 0);
386 show("r - %s (old)\n", member
->ar_name
);
390 char buf
[sizeof(member
->ar_name
) + 2];
391 register char *p
= buf
, *q
= member
->ar_name
;
393 while (q
<= &member
->ar_name
[sizeof(member
->ar_name
)-1] && *q
) {
399 char *mode
= get_mode(member
->ar_mode
);
400 char *date
= ctime(&(member
->ar_date
));
405 print("%s%3u/%u%7ld %s %s %s",
407 (unsigned) (member
->ar_uid
& 0377),
408 (unsigned) (member
->ar_gid
& 0377),
417 show("d - %s\n", member
->ar_name
);
418 lseek(ar_fd
, even(member
->ar_size
), 1);
424 for (i
= 3; i
< argc
; i
++)
425 if (argv
[i
][0] != '\0') {
428 add(argv
[i
], ar_fd
, "a - %s\n");
436 add(argv
[i
], temp_fd
, "a - %s\n");
438 print("%s: not found\n", argv
[i
]);
448 signal(SIGINT
, SIG_IGN
);
451 ar_fd
= open_archive(argv
[2], CREATE
);
452 temp_fd
= open_archive(temp_arch
, APPEND
);
456 while ((read_chars
= read(temp_fd
, io_buffer
, IO_SIZE
)) > 0)
457 mwrite(ar_fd
, io_buffer
, read_chars
);
469 static MEMBER member
;
470 register int read_chars
;
474 if (stat(name
, &status
) < 0) {
475 error(FALSE
, "cannot find %s\n", name
);
478 else if (S_ISDIR(status
.st_mode
)) {
479 error(FALSE
, "%s is a directory (ignored)\n", name
);
482 else if ((src_fd
= open(name
, 0)) < 0) {
483 error(FALSE
, "cannot open %s\n", name
);
487 strncpy (member
.ar_name
, basename (name
), sizeof(member
.ar_name
));
488 member
.ar_uid
= status
.st_uid
;
489 member
.ar_gid
= status
.st_gid
;
490 member
.ar_mode
= status
.st_mode
;
491 member
.ar_date
= status
.st_mtime
;
492 member
.ar_size
= status
.st_size
;
497 member
.ar_mode
= 0644;
498 member
.ar_date
= distr_time
;
501 wr_arhdr(fd
, &member
);
503 do_object(src_fd
, member
.ar_size
);
504 lseek(src_fd
, 0L, 0);
505 offset
+= AR_TOTAL
+ even(member
.ar_size
);
507 while (status
.st_size
> 0) {
511 if (status
.st_size
< x
) {
517 else status
.st_size
-= x
;
518 if (read(src_fd
, io_buffer
, read_chars
) != read_chars
) {
519 error(FALSE
,"%s seems to shrink\n", name
);
522 mwrite(fd
, io_buffer
, x
);
526 show(mess
, member
.ar_name
);
531 register MEMBER
*member
;
534 char buf
[sizeof(member
->ar_name
) + 1];
536 strncpy(buf
, member
->ar_name
, sizeof(member
->ar_name
));
537 buf
[sizeof(member
->ar_name
)] = 0;
538 if (pr_fl
== FALSE
&& (fd
= creat(buf
, 0666)) < 0) {
539 error(FALSE
, "cannot create %s\n", buf
);
544 if (pr_fl
== FALSE
) show("x - %s\n", buf
);
545 else show("\n<%s>\n\n", buf
);
548 copy_member(member
, ar_fd
, fd
, 1);
550 if (fd
>= 0 && fd
!= 1)
552 if (pr_fl
== FALSE
) chmod(buf
, member
->ar_mode
);
555 copy_member(member
, from
, to
, extracting
)
556 register MEMBER
*member
;
560 long mem_size
= member
->ar_size
;
561 BOOL is_odd
= odd(mem_size
) ? TRUE
: FALSE
;
565 long pos
= lseek(from
, 0L, 1);
567 do_object(from
, mem_size
);
568 offset
+= AR_TOTAL
+ even(mem_size
);
573 rest
= mem_size
> (long) IO_SIZE
? IO_SIZE
: (int) mem_size
;
574 if (read(from
, io_buffer
, rest
) != rest
) {
575 char buf
[sizeof(member
->ar_name
) + 1];
577 strncpy(buf
, member
->ar_name
, sizeof(member
->ar_name
));
578 buf
[sizeof(member
->ar_name
)] = 0;
579 error(TRUE
, "read error on %s\n", buf
);
581 if (to
>= 0) mwrite(to
, io_buffer
, rest
);
582 mem_size
-= (long) rest
;
583 } while (mem_size
> 0L);
587 if (to
>= 0 && ! extracting
)
596 static char mode_buf
[11];
597 register int tmp
= mode
;
601 for (i
= 0; i
< 3; i
++) {
602 mode_buf
[i
* 3] = (tmp
& S_IREAD
) ? 'r' : '-';
603 mode_buf
[i
* 3 + 1] = (tmp
& S_IWRITE
) ? 'w' : '-';
604 mode_buf
[i
* 3 + 2] = (tmp
& S_IEXEC
) ? 'x' : '-';
616 error(TRUE
, "write error\n");
621 error(TRUE
, "read error\n");
624 mwrite(fd
, address
, bytes
)
626 register char *address
;
629 if (write(fd
, address
, bytes
) != bytes
)
630 error(TRUE
, "write error\n");
637 char buf
[sizeof(x
.ar_name
)+1];
638 register char *p
= buf
, *q
= name
;
640 while (q
<= &name
[sizeof(x
.ar_name
)-1] && *q
) *p
++ = *q
++;
647 * Write out the ranlib table: first 4 bytes telling how many ranlib structs
648 * there are, followed by the ranlib structs,
649 * then 4 bytes giving the size of the string table, followed by the string
654 register struct ranlib
*ran
;
660 tstrtab
[tssiz
++] = '\0';
661 for (i
= 0; i
< sizeof(arbuf
.ar_name
); i
++)
662 arbuf
.ar_name
[i
] = '\0';
663 strcpy(arbuf
.ar_name
, SYMDEF
);
664 arbuf
.ar_size
= 4 + 2 * 4 * (long)tnum
+ 4 + (long)tssiz
;
665 time(&arbuf
.ar_date
);
666 arbuf
.ar_uid
= getuid();
667 arbuf
.ar_gid
= getgid();
668 arbuf
.ar_mode
= 0444;
673 arbuf
.ar_date
= distr_time
;
676 wr_arhdr(ar_fd
,&arbuf
);
677 wr_long(ar_fd
, (long) tnum
);
679 * Account for the space occupied by the magic number
680 * and the ranlib table.
682 delta
= 2 + AR_TOTAL
+ arbuf
.ar_size
;
683 for (ran
= tab
; ran
< &tab
[tnum
]; ran
++) {
684 ran
->ran_pos
+= delta
;
687 wr_ranlib(ar_fd
, tab
, (long) tnum
);
688 wr_long(ar_fd
, (long) tssiz
);
689 wr_bytes(ar_fd
, tstrtab
, (long) tssiz
);
693 * Return whether the bytes in `buf' form a good object header.
694 * The header is put in `headp'.
698 register struct outhead
*headp
;
701 return !BADMAGIC(*headp
) && headp
->oh_nname
!= 0;
707 struct outhead headbuf
;
709 if (size
< SZ_HEAD
) {
710 /* It can't be an object file. */
714 * Read a header to see if it is an object file.
716 if (! rd_fdopen(f
)) {
720 if (!is_outhead(&headbuf
)) {
727 * First skip the names and read in the string table, then seek back to the
728 * name table and read and write the names one by one. Update the ranlib table
732 struct outhead
*headp
;
734 register char *strings
;
735 register int nnames
= headp
->oh_nname
;
737 struct outname namebuf
[NNAMES
];
738 long xxx
= OFF_CHAR(*headp
);
740 if ( headp
->oh_nchar
!= (unsigned int)headp
->oh_nchar
||
741 (strings
= malloc((unsigned int)headp
->oh_nchar
)) == (char *)0
743 error(TRUE
, "string table too big\n");
745 rd_string(strings
, headp
->oh_nchar
);
747 int i
= nnames
>= NNAMES
? NNAMES
: nnames
;
748 register struct outname
*p
= namebuf
;
753 long off
= p
->on_foff
- xxx
;
754 if (p
->on_foff
== (long)0) {
756 continue; /* An unrecognizable name. */
758 p
->on_mptr
= strings
+ off
;
760 * Only enter names that are exported and are really
761 * defined. Also enter common names. Note, that
762 * this might cause problems when the name is really
763 * defined in a later file, with a value != 0.
764 * However, this problem also exists on the Unix
767 if ( (p
->on_type
& S_EXT
) &&
768 (p
->on_type
& S_TYP
) != S_UND
778 struct outname
*namep
;
783 tab
= (struct ranlib
*)
784 realloc((char *) tab
, (tabsz
+= 512) * sizeof(struct ranlib
));
785 if (! tab
) error(TRUE
, "Out of core\n");
787 tab
[tnum
].ran_off
= tssiz
;
788 tab
[tnum
].ran_pos
= offset
;
790 for (cp
= namep
->on_mptr
;; cp
++) {
791 if (tssiz
>= strtabsz
) {
792 tstrtab
= realloc(tstrtab
, (strtabsz
+= 4096));
793 if (! tstrtab
) error(TRUE
, "string table overflow\n");
795 tstrtab
[tssiz
++] = *cp
;