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