Initial revision
This commit is contained in:
		
							parent
							
								
									6adc4ef78b
								
							
						
					
					
						commit
						3c7511780b
					
				
					 4 changed files with 888 additions and 0 deletions
				
			
		
							
								
								
									
										47
									
								
								util/arch/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								util/arch/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | EMHOME = ../.. | ||||||
|  | EMH = $(EMHOME)/h | ||||||
|  | EMBIN = $(EMHOME)/bin | ||||||
|  | LIB = $(EMHOME)/modules/lib | ||||||
|  | 
 | ||||||
|  | LIBS =	$(LIB)/libobject.a $(LIB)/libprint.a \
 | ||||||
|  | 	$(LIB)/libstring.a $(LIB)/libsystem.a | ||||||
|  | 
 | ||||||
|  | CFLAGS=-O -I$(EMH) | ||||||
|  | 
 | ||||||
|  | all:            arch aal | ||||||
|  | 
 | ||||||
|  | arch:		arch.o | ||||||
|  | 		$(CC) -n -o arch arch.o $(LIBS) | ||||||
|  | 
 | ||||||
|  | aal:		aal.o | ||||||
|  | 		$(CC) -i -o aal aal.o $(LIBS) | ||||||
|  | 
 | ||||||
|  | arch.o:         $(EMH)/arch.h archiver.c | ||||||
|  | 		$(CC) $(CFLAGS) -c archiver.c | ||||||
|  | 		mv archiver.o arch.o | ||||||
|  | 
 | ||||||
|  | aal.o:		$(EMH)/arch.h archiver.c $(EMH)/ranlib.h $(EMH)/out.h | ||||||
|  | 		$(CC) -DAAL $(CFLAGS) -c archiver.c | ||||||
|  | 		mv archiver.o aal.o | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 		rm -f aal arch *.o *.old | ||||||
|  | 
 | ||||||
|  | install :       all | ||||||
|  | 		rm -f $(EMBIN)/arch $(EMBIN)/aal | ||||||
|  | 		cp aal $(EMBIN)/aal | ||||||
|  | 		cp arch $(EMBIN)/arch | ||||||
|  | 		rm -f $(EMHOME)/man/arch.1 $(EMHOME)/man/aal.1 | ||||||
|  | 		cp aal.1 $(EMHOME)/man/aal.1 | ||||||
|  | 		cp arch.1 $(EMHOME)/man/arch.1 | ||||||
|  | 
 | ||||||
|  | cmp :           all | ||||||
|  | 		-cmp aal $(EMBIN)/aal | ||||||
|  | 		-cmp arch $(EMBIN)/arch | ||||||
|  | 		-cmp aal.1 $(EMHOME)/man/aal.1 | ||||||
|  | 		-cmp arch.1 $(EMHOME)/man/arch.1 | ||||||
|  | 
 | ||||||
|  | opr: | ||||||
|  | 		make pr ^ opr | ||||||
|  | pr: | ||||||
|  | 		@pr Makefile archiver.c | ||||||
							
								
								
									
										79
									
								
								util/arch/aal.1
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								util/arch/aal.1
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,79 @@ | ||||||
|  | .\" $Header$ | ||||||
|  | .TH ARCH 1ACK | ||||||
|  | .SH NAME | ||||||
|  | aal \- archive and library maintainer | ||||||
|  | .SH SYNOPSIS | ||||||
|  | .B aal | ||||||
|  | key afile name ... | ||||||
|  | .SH DESCRIPTION | ||||||
|  | .I Aal | ||||||
|  | maintains groups of ACK-object files | ||||||
|  | combined into a single archive file. | ||||||
|  | An index-table is automatically maintained. | ||||||
|  | The link editor | ||||||
|  | .IR led (6) | ||||||
|  | only understands archives made with | ||||||
|  | .IR aal . | ||||||
|  | .PP | ||||||
|  | .I Key | ||||||
|  | is one character from the set | ||||||
|  | .B adrtx, | ||||||
|  | optionally concatenated with | ||||||
|  | one or more of | ||||||
|  | .B vl. | ||||||
|  | .I Afile | ||||||
|  | is the archive file. | ||||||
|  | The | ||||||
|  | .I names | ||||||
|  | are constituent files in the archive file. | ||||||
|  | The meanings of the | ||||||
|  | .I key | ||||||
|  | characters are: | ||||||
|  | .TP | ||||||
|  | .B d | ||||||
|  | Delete the named files from the archive file. | ||||||
|  | .TP | ||||||
|  | .B a | ||||||
|  | Append the named files to the archive file. | ||||||
|  | .TP | ||||||
|  | .B r | ||||||
|  | Replace the named files in the archive file. | ||||||
|  | New files are placed at the end. | ||||||
|  | .TP | ||||||
|  | .B t | ||||||
|  | Print a table of contents of the archive file. | ||||||
|  | If no names are given, all files in the archive are listed. | ||||||
|  | If names are given, only those files are listed. | ||||||
|  | .TP | ||||||
|  | .B x | ||||||
|  | Extract the named files. | ||||||
|  | If no names are given, all files in the archive are | ||||||
|  | extracted. | ||||||
|  | In neither case does | ||||||
|  | .B x | ||||||
|  | alter the archive file. | ||||||
|  | .TP | ||||||
|  | .B v | ||||||
|  | Verbose. | ||||||
|  | Under the verbose option, | ||||||
|  | .I aal | ||||||
|  | gives a file-by-file | ||||||
|  | description of the making of a | ||||||
|  | new archive file from the old archive and the constituent files. | ||||||
|  | When used with | ||||||
|  | .B t, | ||||||
|  | it gives a long listing of all information about the files. | ||||||
|  | .TP | ||||||
|  | .B l | ||||||
|  | Local. | ||||||
|  | Normally | ||||||
|  | .I aal | ||||||
|  | places its temporary files in the directory /tmp. | ||||||
|  | This option causes them to be placed in the local directory. | ||||||
|  | .SH FILES | ||||||
|  | /tmp/ar.* temporaries | ||||||
|  | .SH "SEE ALSO" | ||||||
|  | em_ass(I), arch(V), | ||||||
|  | .SH BUGS | ||||||
|  | If the same file is mentioned twice in an argument list, | ||||||
|  | it may be put in the archive twice. | ||||||
							
								
								
									
										83
									
								
								util/arch/arch.1
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								util/arch/arch.1
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | ||||||
|  | .\" $Header$ | ||||||
|  | .TH ARCH 1ACK | ||||||
|  | .SH NAME | ||||||
|  | arch \- archive and library maintainer | ||||||
|  | .SH SYNOPSIS | ||||||
|  | .B arch | ||||||
|  | key afile name ... | ||||||
|  | .SH DESCRIPTION | ||||||
|  | .I Arch | ||||||
|  | maintains groups of files | ||||||
|  | combined into a single archive file. | ||||||
|  | The Amsterdam compiler kit provides its own archiver with a | ||||||
|  | fixed, machine-independent format, much like the UNIX-V7 | ||||||
|  | archive format. | ||||||
|  | .PP | ||||||
|  | .I Key | ||||||
|  | is one character from the set | ||||||
|  | .B adrtpx, | ||||||
|  | optionally concatenated with | ||||||
|  | one or more of | ||||||
|  | .B vl. | ||||||
|  | .I Afile | ||||||
|  | is the archive file. | ||||||
|  | The | ||||||
|  | .I names | ||||||
|  | are constituent files in the archive file. | ||||||
|  | The meanings of the | ||||||
|  | .I key | ||||||
|  | characters are: | ||||||
|  | .TP | ||||||
|  | .B d | ||||||
|  | Delete the named files from the archive file. | ||||||
|  | .TP | ||||||
|  | .B a | ||||||
|  | Append the named files to the archive file. | ||||||
|  | .TP | ||||||
|  | .B r | ||||||
|  | Replace the named files in the archive file. | ||||||
|  | New files are placed at the end. | ||||||
|  | .TP | ||||||
|  | .B t | ||||||
|  | Print a table of contents of the archive file. | ||||||
|  | If no names are given, all files in the archive are listed. | ||||||
|  | If names are given, only those files are listed. | ||||||
|  | .TP | ||||||
|  | .B p | ||||||
|  | Print the named files in the archive. | ||||||
|  | .TP | ||||||
|  | .B x | ||||||
|  | Extract the named files. | ||||||
|  | If no names are given, all files in the archive are | ||||||
|  | extracted. | ||||||
|  | In neither case does | ||||||
|  | .B x | ||||||
|  | alter the archive file. | ||||||
|  | .TP | ||||||
|  | .B v | ||||||
|  | Verbose. | ||||||
|  | Under the verbose option, | ||||||
|  | .I arch | ||||||
|  | gives a file-by-file | ||||||
|  | description of the making of a | ||||||
|  | new archive file from the old archive and the constituent files. | ||||||
|  | When used with | ||||||
|  | .B t, | ||||||
|  | it gives a long listing of all information about the files. | ||||||
|  | When used with | ||||||
|  | .BR p , | ||||||
|  | it precedes each file with a name. | ||||||
|  | .TP | ||||||
|  | .B l | ||||||
|  | Local. | ||||||
|  | Normally | ||||||
|  | .I arch | ||||||
|  | places its temporary files in the directory /tmp. | ||||||
|  | This option causes them to be placed in the local directory. | ||||||
|  | .SH FILES | ||||||
|  | /tmp/ar.* temporaries | ||||||
|  | .SH "SEE ALSO" | ||||||
|  | em_ass(I), arch(V), | ||||||
|  | .SH BUGS | ||||||
|  | If the same file is mentioned twice in an argument list, | ||||||
|  | it may be put in the archive twice. | ||||||
							
								
								
									
										679
									
								
								util/arch/archiver.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										679
									
								
								util/arch/archiver.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,679 @@ | ||||||
|  | /* ar - archiver		Author: Michiel Huisjes */ | ||||||
|  | /* Made into arch/aal by Ceriel Jacobs
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static char RcsId[] = "$Header$"; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Usage: [arch|aal] [adprtvx] archive [file] ... | ||||||
|  |  *	  v: verbose | ||||||
|  |  *	  x: extract | ||||||
|  |  *	  a: append | ||||||
|  |  *	  r: replace (append when not in archive) | ||||||
|  |  *	  d: delete | ||||||
|  |  *	  t: print contents of archive | ||||||
|  |  *	  p: print named files | ||||||
|  |  *	  l: temporaries in current directory instead of /tmp | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <arch.h> | ||||||
|  | #ifdef AAL | ||||||
|  | #include <ranlib.h> | ||||||
|  | #include <out.h> | ||||||
|  | #define MAGIC_NUMBER	AALMAG | ||||||
|  | #ifdef AAL | ||||||
|  | #define TABSZ	2000		/* maximum # of ranlib table entries */ | ||||||
|  | #define STRTABSZ	8*TABSZ	/* maximum size of string table */ | ||||||
|  | long	offset; | ||||||
|  | struct ranlib tab[TABSZ]; | ||||||
|  | long	tnum = 0; | ||||||
|  | char	tstrtab[STRTABSZ]; | ||||||
|  | long	tssiz = 0; | ||||||
|  | char	*malloc(), *strcpy(); | ||||||
|  | long	tell(); | ||||||
|  | long	time(); | ||||||
|  | #endif AAL | ||||||
|  | #else | ||||||
|  | #define MAGIC_NUMBER	ARMAG | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define odd(nr)		(nr & 01) | ||||||
|  | #define even(nr)	(odd(nr) ? nr + 1 : nr) | ||||||
|  | 
 | ||||||
|  | typedef char BOOL; | ||||||
|  | #define FALSE		0 | ||||||
|  | #define TRUE		1 | ||||||
|  | 
 | ||||||
|  | #define READ		0 | ||||||
|  | #define APPEND		2 | ||||||
|  | #define CREATE		1 | ||||||
|  | 
 | ||||||
|  | #define MEMBER		struct ar_hdr | ||||||
|  | 
 | ||||||
|  | #define NIL_PTR		((char *) 0) | ||||||
|  | #define NIL_MEM		((MEMBER *) 0) | ||||||
|  | #define NIL_LONG	((long *) 0) | ||||||
|  | 
 | ||||||
|  | #define IO_SIZE		(10 * 1024) | ||||||
|  | 
 | ||||||
|  | #define equal(str1, str2)	(!strncmp((str1), (str2), 14)) | ||||||
|  | 
 | ||||||
|  | BOOL verbose; | ||||||
|  | BOOL app_fl; | ||||||
|  | BOOL ex_fl; | ||||||
|  | BOOL show_fl; | ||||||
|  | BOOL pr_fl; | ||||||
|  | BOOL rep_fl; | ||||||
|  | BOOL del_fl; | ||||||
|  | BOOL local_fl; | ||||||
|  | 
 | ||||||
|  | int ar_fd; | ||||||
|  | 
 | ||||||
|  | char io_buffer[IO_SIZE]; | ||||||
|  | 
 | ||||||
|  | char *progname; | ||||||
|  | 
 | ||||||
|  | char temp_buf[32]; | ||||||
|  | char *temp_arch = &temp_buf[0]; | ||||||
|  | extern char *mktemp(); | ||||||
|  | extern char *ctime(); | ||||||
|  | 
 | ||||||
|  | usage() | ||||||
|  | { | ||||||
|  | 	error(TRUE, "usage: %s %s archive [file] ...\n", | ||||||
|  | 		progname, | ||||||
|  | #ifdef AAL | ||||||
|  | 		"[adrtxvl]" | ||||||
|  | #else | ||||||
|  | 		"[adprtxvl]" | ||||||
|  | #endif | ||||||
|  | 		); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*VARARGS2*/ | ||||||
|  | error(quit, str1, str2, str3, str4) | ||||||
|  | BOOL quit; | ||||||
|  | char *str1, *str2, *str3, *str4; | ||||||
|  | { | ||||||
|  | 	char errbuf[256]; | ||||||
|  | 
 | ||||||
|  | 	sprint(errbuf, str1, str2, str3, str4); | ||||||
|  | 	write(2, errbuf, strlen(errbuf)); | ||||||
|  |   	if (quit) { | ||||||
|  | 		unlink(temp_arch); | ||||||
|  | 		_exit(1); | ||||||
|  |   	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char *basename(path) | ||||||
|  | char *path; | ||||||
|  | { | ||||||
|  |   register char *ptr = path; | ||||||
|  |   register char *last = NIL_PTR; | ||||||
|  | 
 | ||||||
|  |   while (*ptr != '\0') { | ||||||
|  | 	if (*ptr == '/') | ||||||
|  | 		last = ptr; | ||||||
|  | 	ptr++; | ||||||
|  |   } | ||||||
|  |   if (last == NIL_PTR) | ||||||
|  | 	return path; | ||||||
|  |   if (*(last + 1) == '\0') { | ||||||
|  | 	*last = '\0'; | ||||||
|  | 	return basename(path); | ||||||
|  |   } | ||||||
|  |   return last + 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extern unsigned int rd_unsigned2(); | ||||||
|  | 
 | ||||||
|  | open_archive(name, mode) | ||||||
|  | register char *name; | ||||||
|  | register int mode; | ||||||
|  | { | ||||||
|  |   unsigned short magic = 0; | ||||||
|  |   int fd; | ||||||
|  | 
 | ||||||
|  |   if (mode == CREATE) { | ||||||
|  | 	if ((fd = creat(name, 0644)) < 0) | ||||||
|  | 		error(TRUE, "cannot creat %s\n", name); | ||||||
|  | 	magic = MAGIC_NUMBER; | ||||||
|  | 	wr_int2(fd, magic); | ||||||
|  | 	return fd; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if ((fd = open(name, mode)) < 0) { | ||||||
|  | 	if (mode == APPEND) { | ||||||
|  | 		close(open_archive(name, CREATE)); | ||||||
|  | 		error(FALSE, "%s: creating %s\n", progname, name); | ||||||
|  | 		return open_archive(name, APPEND); | ||||||
|  | 	} | ||||||
|  | 	error(TRUE, "cannot open %s\n", name); | ||||||
|  |   } | ||||||
|  |   lseek(fd, 0L, 0); | ||||||
|  |   magic = rd_unsigned2(fd); | ||||||
|  |   if (magic != MAGIC_NUMBER) | ||||||
|  | 	error(TRUE, "%s is not in ar format\n", name); | ||||||
|  |    | ||||||
|  |   return fd; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | catch() | ||||||
|  | { | ||||||
|  | 	unlink(temp_arch); | ||||||
|  | 	_exit (2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | main(argc, argv) | ||||||
|  | int argc; | ||||||
|  | char *argv[]; | ||||||
|  | { | ||||||
|  |   register char *ptr; | ||||||
|  |   int pow, pid; | ||||||
|  | 
 | ||||||
|  |   progname = argv[0]; | ||||||
|  | 
 | ||||||
|  |   if (argc < 3) | ||||||
|  | 	usage(); | ||||||
|  |    | ||||||
|  |   for (ptr = argv[1]; *ptr; ptr++) { | ||||||
|  | 	switch (*ptr) { | ||||||
|  | 		case 't' : | ||||||
|  | 			show_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		case 'v' : | ||||||
|  | 			verbose = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		case 'x' : | ||||||
|  | 			ex_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		case 'a' : | ||||||
|  | 			app_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | #ifndef AAL | ||||||
|  | 		case 'p' : | ||||||
|  | 			pr_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | #endif | ||||||
|  | 		case 'd' : | ||||||
|  | 			del_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		case 'r' : | ||||||
|  | 			rep_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		case 'l' : | ||||||
|  | 			local_fl = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		default : | ||||||
|  | 			usage(); | ||||||
|  | 	} | ||||||
|  |   } | ||||||
|  |   if (local_fl) strcpy(temp_arch, "ar.XXXXXX"); | ||||||
|  |   else	strcpy(temp_arch, "/tmp/ar.XXXXXX"); | ||||||
|  | 
 | ||||||
|  |   if (app_fl + ex_fl + del_fl + rep_fl + show_fl + pr_fl != 1) | ||||||
|  | 	usage(); | ||||||
|  |    | ||||||
|  |   if (rep_fl || del_fl | ||||||
|  | #ifdef AAL | ||||||
|  | 	|| app_fl | ||||||
|  | #endif | ||||||
|  |      ) { | ||||||
|  | 	mktemp(temp_arch); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   signal(SIGINT, catch); | ||||||
|  |   get(argc, argv); | ||||||
|  |    | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MEMBER * | ||||||
|  | get_member() | ||||||
|  | { | ||||||
|  |   static MEMBER member; | ||||||
|  |   register int ret; | ||||||
|  | 
 | ||||||
|  | again: | ||||||
|  |   if ((ret = rd_arhdr(ar_fd, &member)) == 0) | ||||||
|  | 	return NIL_MEM; | ||||||
|  | #ifdef AAL | ||||||
|  |   if (equal(SYMDEF, member.ar_name)) { | ||||||
|  | 	lseek(ar_fd, member.ar_size, 1); | ||||||
|  | 	goto again; | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |   return &member; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char *get_mode(); | ||||||
|  | 
 | ||||||
|  | get(argc, argv) | ||||||
|  | int argc; | ||||||
|  | register char *argv[]; | ||||||
|  | { | ||||||
|  |   register MEMBER *member; | ||||||
|  |   int i = 0; | ||||||
|  |   int temp_fd, read_chars; | ||||||
|  | 
 | ||||||
|  |   ar_fd = open_archive(argv[2], (show_fl || pr_fl) ? READ : APPEND); | ||||||
|  |   if (rep_fl || del_fl | ||||||
|  | #ifdef AAL | ||||||
|  | 	|| app_fl | ||||||
|  | #endif | ||||||
|  |   ) | ||||||
|  | 	temp_fd = open_archive(temp_arch, CREATE); | ||||||
|  |   while ((member = get_member()) != NIL_MEM) { | ||||||
|  | 	if (argc > 3) { | ||||||
|  | 		for (i = 3; i < argc; i++) { | ||||||
|  | 			if (equal(basename(argv[i]), member->ar_name)) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		if (i == argc || app_fl) { | ||||||
|  | 			if (rep_fl || del_fl | ||||||
|  | #ifdef AAL | ||||||
|  | 				|| app_fl | ||||||
|  | #endif | ||||||
|  | 			) { | ||||||
|  | #ifdef AAL | ||||||
|  | 				if (i != argc) { | ||||||
|  | 					print("%s: already in archive\n", argv[i]); | ||||||
|  | 					argv[i] = ""; | ||||||
|  | 				} | ||||||
|  | #endif | ||||||
|  | 				wr_arhdr(temp_fd, member); | ||||||
|  | 				copy_member(member, ar_fd, temp_fd, 0); | ||||||
|  | 			} | ||||||
|  | #ifndef AAL | ||||||
|  | 			else { | ||||||
|  | 				if (app_fl && i != argc) { | ||||||
|  | 					print("%s: already in archive\n", argv[i]); | ||||||
|  | 					argv[i] = ""; | ||||||
|  | 				} | ||||||
|  | 				lseek(ar_fd, even(member->ar_size),1); | ||||||
|  | 			} | ||||||
|  | #endif | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (ex_fl || pr_fl) | ||||||
|  | 		extract(member); | ||||||
|  | 	else { | ||||||
|  | 		if (rep_fl) | ||||||
|  | 			add(argv[i], temp_fd, "r - %s\n"); | ||||||
|  | 		else if (show_fl) { | ||||||
|  | 			char buf[sizeof(member->ar_name) + 2]; | ||||||
|  | 			register char *p = buf, *q = member->ar_name; | ||||||
|  | 
 | ||||||
|  | 			while (q <= &member->ar_name[sizeof(member->ar_name)-1] && *q) { | ||||||
|  | 				*p++ = *q++; | ||||||
|  | 			} | ||||||
|  | 			*p++ = '\n'; | ||||||
|  | 			*p = '\0'; | ||||||
|  | 			if (verbose) { | ||||||
|  | 				char *mode = get_mode(member->ar_mode); | ||||||
|  | 				char *date = ctime(&(member->ar_date)); | ||||||
|  | 
 | ||||||
|  | 				*(date + 16) = '\0'; | ||||||
|  | 				*(date + 24) = '\0'; | ||||||
|  | 
 | ||||||
|  | 				print("%s%3u/%u%7ld %s %s %s", | ||||||
|  | 					mode, | ||||||
|  | 					(unsigned) member->ar_uid, | ||||||
|  | 					(unsigned) member->ar_gid, | ||||||
|  | 					member->ar_size, | ||||||
|  | 					date+4, | ||||||
|  | 					date+20, | ||||||
|  | 					buf); | ||||||
|  | 			} | ||||||
|  | 			else	print(buf); | ||||||
|  | 		} | ||||||
|  | 		else if (del_fl) | ||||||
|  | 			show("d - %s\n", member->ar_name); | ||||||
|  | 		lseek(ar_fd, even(member->ar_size), 1); | ||||||
|  | 	} | ||||||
|  | 	argv[i] = ""; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (argc > 3) { | ||||||
|  | 	for (i = 3; i < argc; i++) | ||||||
|  | 		if (argv[i][0] != '\0') { | ||||||
|  | #ifndef AAL | ||||||
|  | 			if (app_fl) | ||||||
|  | 				add(argv[i], ar_fd, "a - %s\n"); | ||||||
|  | 			else | ||||||
|  | #endif | ||||||
|  | 			if (rep_fl | ||||||
|  | #ifdef AAL | ||||||
|  | 				|| app_fl | ||||||
|  | #endif | ||||||
|  | 			) | ||||||
|  | 				add(argv[i], temp_fd, "a - %s\n"); | ||||||
|  | 			else { | ||||||
|  | 				print("%s: not found\n", argv[i]); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (rep_fl || del_fl | ||||||
|  | #ifdef AAL | ||||||
|  | 		|| app_fl | ||||||
|  | #endif | ||||||
|  |   ) { | ||||||
|  | 	signal(SIGINT, SIG_IGN); | ||||||
|  | 	close(ar_fd); | ||||||
|  | 	close(temp_fd); | ||||||
|  | 	ar_fd = open_archive(argv[2], CREATE); | ||||||
|  | 	temp_fd = open_archive(temp_arch, APPEND); | ||||||
|  | #ifdef AAL | ||||||
|  | 	write_symdef(); | ||||||
|  | #endif | ||||||
|  | 	while ((read_chars = read(temp_fd, io_buffer, IO_SIZE)) > 0) | ||||||
|  | 		mwrite(ar_fd, io_buffer, read_chars); | ||||||
|  | 	close(temp_fd); | ||||||
|  | 	unlink(temp_arch); | ||||||
|  |   } | ||||||
|  |   close(ar_fd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | add(name, fd, mess) | ||||||
|  | char *name; | ||||||
|  | int fd; | ||||||
|  | char *mess; | ||||||
|  | { | ||||||
|  |   static MEMBER member; | ||||||
|  |   register int read_chars; | ||||||
|  |   struct stat status; | ||||||
|  |   int src_fd; | ||||||
|  | 
 | ||||||
|  |   if (stat(name, &status) < 0) { | ||||||
|  | 	error(FALSE, "cannot find %s\n", name); | ||||||
|  | 	return; | ||||||
|  |   } | ||||||
|  |   else if ((src_fd = open(name, 0)) < 0) { | ||||||
|  | 	error(FALSE, "cannot open %s\n", name); | ||||||
|  | 	return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   strncpy (member.ar_name, basename (name), sizeof(member.ar_name)); | ||||||
|  |   member.ar_uid = status.st_uid; | ||||||
|  |   member.ar_gid = status.st_gid; | ||||||
|  |   member.ar_mode = status.st_mode; | ||||||
|  |   member.ar_date = status.st_mtime; | ||||||
|  |   member.ar_size = status.st_size; | ||||||
|  |   wr_arhdr(fd, &member); | ||||||
|  | #ifdef AAL | ||||||
|  |   do_object(src_fd, member.ar_size); | ||||||
|  |   lseek(src_fd, 0L, 0); | ||||||
|  |   offset += AR_TOTAL + even(member.ar_size); | ||||||
|  | #endif | ||||||
|  |   while (status.st_size > 0) { | ||||||
|  | 	int x = IO_SIZE; | ||||||
|  | 
 | ||||||
|  | 	read_chars = x; | ||||||
|  | 	if (status.st_size < x) { | ||||||
|  | 		x = status.st_size; | ||||||
|  | 		read_chars = x; | ||||||
|  | 		status.st_size = 0; | ||||||
|  | 		x = even(x); | ||||||
|  | 	} | ||||||
|  | 	else	status.st_size -= x; | ||||||
|  |   	if (read(src_fd, io_buffer, read_chars) != read_chars) | ||||||
|  | 		error(FALSE,"%s seems to shrink\n", name); | ||||||
|  | 	mwrite(fd, io_buffer, x); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (verbose) | ||||||
|  | 	show(mess, name); | ||||||
|  |   close(src_fd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extract(member) | ||||||
|  | register MEMBER *member; | ||||||
|  | { | ||||||
|  |   int fd = 1; | ||||||
|  | 
 | ||||||
|  |   if (pr_fl == FALSE && (fd = creat(member->ar_name, 0644)) < 0) { | ||||||
|  | 	error(FALSE, "cannot create %s\n", member->ar_name); | ||||||
|  | 	return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (verbose) { | ||||||
|  | 	if (pr_fl == FALSE) show("x - %s\n", member->ar_name); | ||||||
|  | 	else show("\n<%s>\n\n", member->ar_name); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   copy_member(member, ar_fd, fd, 1); | ||||||
|  | 
 | ||||||
|  |   if (fd != 1) | ||||||
|  |   	close(fd); | ||||||
|  |   if (pr_fl == FALSE) chmod(member->ar_name, member->ar_mode); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | copy_member(member, from, to, extracting) | ||||||
|  | register MEMBER *member; | ||||||
|  | int from, to; | ||||||
|  | { | ||||||
|  |   register int rest; | ||||||
|  |   long mem_size = member->ar_size; | ||||||
|  |   BOOL is_odd = odd(mem_size) ? TRUE : FALSE; | ||||||
|  | 
 | ||||||
|  | #ifdef AAL | ||||||
|  |   if (! extracting) { | ||||||
|  |   	long pos = lseek(from, 0L, 1); | ||||||
|  | 
 | ||||||
|  | 	do_object(from, mem_size); | ||||||
|  | 	offset += AR_TOTAL + even(mem_size); | ||||||
|  |   	lseek(from, pos, 0); | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|  |   do { | ||||||
|  | 	rest = mem_size > (long) IO_SIZE ? IO_SIZE : (int) mem_size; | ||||||
|  | 	if (read(from, io_buffer, rest) != rest) | ||||||
|  | 		error(TRUE, "read error on %s\n", member->ar_name); | ||||||
|  | 	mwrite(to, io_buffer, rest); | ||||||
|  | 	mem_size -= (long) rest; | ||||||
|  |   } while (mem_size != 0L); | ||||||
|  | 
 | ||||||
|  |   if (is_odd) { | ||||||
|  | 	lseek(from, 1L, 1); | ||||||
|  | 	if (! extracting) | ||||||
|  | 		lseek(to, 1L, 1); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | get_mode(mode) | ||||||
|  | register int mode; | ||||||
|  | { | ||||||
|  |   static char mode_buf[11]; | ||||||
|  |   register int tmp = mode; | ||||||
|  |   int i; | ||||||
|  | 
 | ||||||
|  |   mode_buf[9] = ' '; | ||||||
|  |   for (i = 0; i < 3; i++) { | ||||||
|  | 	mode_buf[i * 3] = (tmp & S_IREAD) ? 'r' : '-'; | ||||||
|  | 	mode_buf[i * 3 + 1] = (tmp & S_IWRITE) ? 'w' : '-'; | ||||||
|  | 	mode_buf[i * 3 + 2] = (tmp & S_IEXEC) ? 'x' : '-'; | ||||||
|  | 	tmp <<= 3; | ||||||
|  |   } | ||||||
|  |   if (mode & S_ISUID) | ||||||
|  | 	mode_buf[2] = 's'; | ||||||
|  |   if (mode & S_ISGID) | ||||||
|  | 	mode_buf[5] = 's'; | ||||||
|  |   return mode_buf; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | wr_fatal() | ||||||
|  | { | ||||||
|  | 	error(TRUE, "write error\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | rd_fatal() | ||||||
|  | { | ||||||
|  | 	error(TRUE, "read error\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | mwrite(fd, address, bytes) | ||||||
|  | int fd; | ||||||
|  | register char *address; | ||||||
|  | register int bytes; | ||||||
|  | { | ||||||
|  |   if (write(fd, address, bytes) != bytes) | ||||||
|  | 	error(TRUE, "write error\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | show(s, name) | ||||||
|  | char *s, *name; | ||||||
|  | { | ||||||
|  |   MEMBER x; | ||||||
|  |   char buf[sizeof(x.ar_name)+1]; | ||||||
|  |   register char *p = buf, *q = name; | ||||||
|  | 
 | ||||||
|  |   while (q <= &name[sizeof(x.ar_name)-1] && *q) *p++ = *q++; | ||||||
|  |   *p++ = '\0'; | ||||||
|  |   print(s, buf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef AAL | ||||||
|  | /*
 | ||||||
|  |  * Write out the ranlib table: first 4 bytes telling how many ranlib structs | ||||||
|  |  * there are, followed by the ranlib structs, | ||||||
|  |  * then 4 bytes giving the size of the string table, followed by the string | ||||||
|  |  * table itself. | ||||||
|  |  */ | ||||||
|  | write_symdef() | ||||||
|  | { | ||||||
|  | 	register struct ranlib	*ran; | ||||||
|  | 	register char	*str; | ||||||
|  | 	register int	i; | ||||||
|  | 	register long	delta; | ||||||
|  | 	MEMBER	arbuf; | ||||||
|  | 
 | ||||||
|  | 	if (odd(tssiz)) | ||||||
|  | 		tstrtab[tssiz++] = '\0'; | ||||||
|  | 	for (i = 0; i < sizeof(arbuf.ar_name); i++) | ||||||
|  | 		arbuf.ar_name[i] = '\0'; | ||||||
|  | 	strcpy(arbuf.ar_name, SYMDEF); | ||||||
|  | 	arbuf.ar_size = 4 + 2 * 4 * tnum + 4 + tssiz; | ||||||
|  | 	time(&arbuf.ar_date); | ||||||
|  | 	arbuf.ar_uid = getuid(); | ||||||
|  | 	arbuf.ar_gid = getgid(); | ||||||
|  | 	arbuf.ar_mode = 0444; | ||||||
|  | 	wr_arhdr(ar_fd,&arbuf); | ||||||
|  | 	wr_long(ar_fd, tnum); | ||||||
|  | 	/*
 | ||||||
|  | 	 * Account for the space occupied by the magic number | ||||||
|  | 	 * and the ranlib table. | ||||||
|  | 	 */ | ||||||
|  | 	delta = 2 + AR_TOTAL + arbuf.ar_size; | ||||||
|  | 	for (ran = tab; ran < &tab[tnum]; ran++) { | ||||||
|  | 		ran->ran_pos += delta; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wr_ranlib(ar_fd, tab, tnum); | ||||||
|  | 	wr_long(ar_fd, tssiz); | ||||||
|  | 	wr_bytes(ar_fd, tstrtab, tssiz); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Return whether the bytes in `buf' form a good object header.  | ||||||
|  |  * The header is put in `headp'. | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | is_outhead(headp) | ||||||
|  | 	register struct outhead	*headp; | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | 	return !BADMAGIC(*headp) && headp->oh_nname != 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_object(f, size) | ||||||
|  | 	long size; | ||||||
|  | { | ||||||
|  | 	struct outhead	headbuf; | ||||||
|  | 
 | ||||||
|  | 	if (size < SZ_HEAD) { | ||||||
|  | 		/* It can't be an object file. */ | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	/*
 | ||||||
|  | 	 * Read a header to see if it is an object file. | ||||||
|  | 	 */ | ||||||
|  | 	if (! rd_fdopen(f)) { | ||||||
|  | 		rd_fatal(); | ||||||
|  | 	} | ||||||
|  | 	rd_ohead(&headbuf); | ||||||
|  | 	if (!is_outhead(&headbuf)) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	do_names(&headbuf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * First skip the names and read in the string table, then seek back to the | ||||||
|  |  * name table and read and write the names one by one. Update the ranlib table | ||||||
|  |  * accordingly. | ||||||
|  |  */ | ||||||
|  | do_names(headp) | ||||||
|  | 	struct outhead	*headp; | ||||||
|  | { | ||||||
|  | 	register char	*strings; | ||||||
|  | 	register int	nnames = headp->oh_nname; | ||||||
|  | #define NNAMES 100 | ||||||
|  | 	struct outname	namebuf[NNAMES]; | ||||||
|  | 	char *xxx; | ||||||
|  | 
 | ||||||
|  | 	if (	headp->oh_nchar != (unsigned int)headp->oh_nchar || | ||||||
|  | 		(strings = malloc((unsigned int)headp->oh_nchar)) == (char *)0 | ||||||
|  | 	   ) { | ||||||
|  | 		error(TRUE, "string table too big\n"); | ||||||
|  | 	} | ||||||
|  | 	rd_string(strings, headp->oh_nchar); | ||||||
|  | 	xxx = strings - OFF_CHAR(*headp); | ||||||
|  | 	while (nnames) { | ||||||
|  | 		int i = nnames >= NNAMES ? NNAMES : nnames; | ||||||
|  | 		register struct outname *p = namebuf; | ||||||
|  | 
 | ||||||
|  | 		nnames -= i; | ||||||
|  | 		rd_name(namebuf, i); | ||||||
|  | 		while (i--) { | ||||||
|  | 			if (p->on_foff == (long)0) | ||||||
|  | 				continue; /* An unrecognizable name. */ | ||||||
|  | 			p->on_mptr = xxx + p->on_foff; | ||||||
|  | 			/*
 | ||||||
|  | 			 * Only enter names that are exported and are really | ||||||
|  | 			 * defined. | ||||||
|  | 			 */ | ||||||
|  | 			if (	(p->on_type & S_EXT) && | ||||||
|  | 				(p->on_type & S_TYP) != S_UND && | ||||||
|  | 				!(p->on_type & S_COM) | ||||||
|  | 			   ) | ||||||
|  | 				enter_name(p); | ||||||
|  | 			p++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	free(strings); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enter_name(namep) | ||||||
|  | 	struct outname *namep; | ||||||
|  | { | ||||||
|  | 	register char	*cp; | ||||||
|  | 
 | ||||||
|  | 	if (tnum >= TABSZ) { | ||||||
|  | 		error(TRUE, "symbol table overflow\n"); | ||||||
|  | 	} | ||||||
|  | 	tab[tnum].ran_off = tssiz; | ||||||
|  | 	tab[tnum].ran_pos = offset; | ||||||
|  | 
 | ||||||
|  | 	for (cp = namep->on_mptr; tstrtab[tssiz++] = *cp++;) | ||||||
|  | 		if (tssiz >= STRTABSZ) { | ||||||
|  | 			error(TRUE, "string table overflow\n"); | ||||||
|  | 		} | ||||||
|  | 	tnum++; | ||||||
|  | } | ||||||
|  | #endif AAL | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue