You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							229 lines
						
					
					
						
							5.0 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							229 lines
						
					
					
						
							5.0 KiB
						
					
					
				
								/* LINTLIBRARY */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*
							 | 
						|
								 * saveimage.c --
							 | 
						|
								 *
							 | 
						|
								 * Function to save an executable copy of the current process's
							 | 
						|
								 * image in a file.
							 | 
						|
								 *
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#include <stdio.h>
							 | 
						|
								#include "util.h"
							 | 
						|
								
							 | 
						|
								#ifdef BSD
							 | 
						|
								#include <sys/types.h>
							 | 
						|
								#include <sys/stat.h>
							 | 
						|
								#include <a.out.h>
							 | 
						|
								#include <errno.h>
							 | 
						|
								
							 | 
						|
								extern int errno;
							 | 
						|
								
							 | 
						|
								#define	BUFSIZE		8192
							 | 
						|
								
							 | 
						|
								extern long lseek();	/* For lint */
							 | 
						|
								extern int getpagesize();
							 | 
						|
								extern char *sbrk();
							 | 
						|
								
							 | 
						|
								static int copy_file();
							 | 
						|
								static int pad_file();
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								int
							 | 
						|
								util_save_image(char const *orig_file_name, char const *save_file_name)
							 | 
						|
								{
							 | 
						|
								    int origFd = -1, saveFd = -1;
							 | 
						|
								    char *start_data, *end_data, *start_text, *end_round;
							 | 
						|
								    struct exec old_hdr, new_hdr;
							 | 
						|
								    struct stat old_stat;
							 | 
						|
								    int n, page_size, length_text, length_data;
							 | 
						|
								
							 | 
						|
								    if ((origFd = open(orig_file_name, 0)) < 0) {
							 | 
						|
									perror(orig_file_name);
							 | 
						|
									(void) fprintf(stderr, "Cannot open original a.out file\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (fstat(origFd, &old_stat) < 0) {
							 | 
						|
									perror(orig_file_name);
							 | 
						|
									(void) fprintf(stderr, "Cannot stat original a.out file\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     * Read the a.out header from the original file.
							 | 
						|
								     */
							 | 
						|
								    if (read(origFd, (char *) &old_hdr, sizeof(old_hdr)) != sizeof(old_hdr)) {
							 | 
						|
									perror(orig_file_name);
							 | 
						|
									(void) fprintf(stderr, "Cannot read original a.out header\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								    if (N_BADMAG(old_hdr)) {
							 | 
						|
									(void) fprintf(stderr, "File %s has a bad magic number (%o)\n",
							 | 
						|
											orig_file_name, old_hdr.a_magic);
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								    if (old_hdr.a_magic != ZMAGIC) {
							 | 
						|
									(void) fprintf(stderr, "File %s is not demand-paged\n", orig_file_name);
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     * Open the output file.
							 | 
						|
								     */
							 | 
						|
								    if (access(save_file_name, /* F_OK */ 0) == 0) {
							 | 
						|
									(void) unlink(save_file_name);
							 | 
						|
								    }
							 | 
						|
								    if ((saveFd = creat(save_file_name, 0777)) < 0) {
							 | 
						|
									if (errno == ETXTBSY) {
							 | 
						|
									    (void) unlink(save_file_name);
							 | 
						|
									    saveFd = creat(save_file_name, 0777);
							 | 
						|
									}
							 | 
						|
									if (saveFd < 0) {
							 | 
						|
									    perror(save_file_name);
							 | 
						|
									    (void) fprintf(stderr, "Cannot create save file.\n");
							 | 
						|
									    goto bad;
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     * Find out how far the data segment extends.
							 | 
						|
								     */
							 | 
						|
								    new_hdr = old_hdr;
							 | 
						|
								    end_data = sbrk(0);
							 | 
						|
								    page_size = getpagesize();
							 | 
						|
								    n = ((((int) end_data) + page_size - 1) / page_size) * page_size;
							 | 
						|
								    end_round = (char *) n;
							 | 
						|
								    if (end_round > end_data) {
							 | 
						|
									end_data = sbrk(end_round - end_data);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								#ifdef vax
							 | 
						|
								    start_text = 0;
							 | 
						|
								    length_text = new_hdr.a_text;
							 | 
						|
								    start_data = (char *) old_hdr.a_text;
							 | 
						|
								    length_data = end_data - start_data;
							 | 
						|
								#endif vax
							 | 
						|
								#ifdef	sun
							 | 
						|
								    start_text = (char *) N_TXTADDR(old_hdr) + sizeof(old_hdr);
							 | 
						|
								    length_text = old_hdr.a_text - sizeof(old_hdr);
							 | 
						|
								    start_data = (char *) N_DATADDR(old_hdr);
							 | 
						|
								    length_data = end_data - start_data;
							 | 
						|
								#endif	sun
							 | 
						|
								    new_hdr.a_data = end_data - start_data;
							 | 
						|
								    new_hdr.a_bss = 0;
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     * First, the header plus enough pad to extend up to N_TXTOFF.
							 | 
						|
								     */
							 | 
						|
								    if (write(saveFd, (char *) &new_hdr, (int) sizeof(new_hdr)) !=
							 | 
						|
												sizeof(new_hdr)) {
							 | 
						|
									perror("write");
							 | 
						|
									(void) fprintf(stderr, "Error while copying header.\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								    if (! pad_file(saveFd, N_TXTOFF(old_hdr) - sizeof(new_hdr))) {
							 | 
						|
									(void) fprintf(stderr, "Error while padding.\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     *  Copy our text segment
							 | 
						|
								     */
							 | 
						|
								    if (write(saveFd, start_text, length_text) != length_text) {
							 | 
						|
									perror("write");
							 | 
						|
									(void) fprintf(stderr, "Error while copying text segment.\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     *  Copy our data segment
							 | 
						|
								     */
							 | 
						|
								    if (write(saveFd, start_data, length_data) != length_data) {
							 | 
						|
									perror("write");
							 | 
						|
									(void) fprintf(stderr, "Error while copying data segment.\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /*
							 | 
						|
								     * Copy the symbol table and everything else.
							 | 
						|
								     * This takes us to the end of the original file.
							 | 
						|
								     */
							 | 
						|
								    (void) lseek(origFd, (long) N_SYMOFF(old_hdr), 0);
							 | 
						|
								    if (! copy_file(origFd, saveFd, old_stat.st_size - N_SYMOFF(old_hdr))) {
							 | 
						|
									(void) fprintf(stderr, "Error while copying symbol table.\n");
							 | 
						|
									goto bad;
							 | 
						|
								    }
							 | 
						|
								    (void) close(origFd);
							 | 
						|
								    (void) close(saveFd);
							 | 
						|
								    return 1;
							 | 
						|
								
							 | 
						|
								bad:
							 | 
						|
								    if (origFd >= 0) (void) close(origFd);
							 | 
						|
								    if (saveFd >= 0) (void) close(saveFd);
							 | 
						|
								    return 0;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								static int
							 | 
						|
								copy_file(inFd, outFd, nbytes)
							 | 
						|
								int inFd, outFd;
							 | 
						|
								unsigned long nbytes;
							 | 
						|
								{
							 | 
						|
								    char buf[BUFSIZE];
							 | 
						|
								    int nread, ntoread;
							 | 
						|
								
							 | 
						|
								    while (nbytes > 0) {
							 | 
						|
									ntoread = nbytes;
							 | 
						|
									if (ntoread > sizeof buf) ntoread = sizeof buf;
							 | 
						|
									if ((nread = read(inFd, buf, ntoread)) != ntoread) {
							 | 
						|
									    perror("read");
							 | 
						|
									    return (0);
							 | 
						|
									}
							 | 
						|
									if (write(outFd, buf, nread) != nread) {
							 | 
						|
									    perror("write");
							 | 
						|
									    return (0);
							 | 
						|
									}
							 | 
						|
									nbytes -= nread;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return (1);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								static int
							 | 
						|
								pad_file(outFd, nbytes)
							 | 
						|
								int outFd;
							 | 
						|
								int nbytes;
							 | 
						|
								{
							 | 
						|
								    char buf[BUFSIZE];
							 | 
						|
								    int nzero;
							 | 
						|
								
							 | 
						|
								    nzero = (nbytes > sizeof(buf)) ? sizeof(buf) : nbytes;
							 | 
						|
								    bzero(buf, nzero);
							 | 
						|
								    while (nbytes > 0) {
							 | 
						|
									nzero = (nbytes > sizeof(buf)) ? sizeof(buf) : nbytes;
							 | 
						|
									if (write(outFd, buf, nzero) != nzero) {
							 | 
						|
									    perror("write");
							 | 
						|
									    return (0);
							 | 
						|
									}
							 | 
						|
									nbytes -= nzero;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return (1);
							 | 
						|
								}
							 | 
						|
								#else
							 | 
						|
								
							 | 
						|
								/* ARGSUSED */
							 | 
						|
								int
							 | 
						|
								util_save_image(char const *orig_file_name, char const *save_file_name)
							 | 
						|
								{
							 | 
						|
								    (void) fprintf(stderr, 
							 | 
						|
									"util_save_image: not implemented on your operating system\n");
							 | 
						|
								    return 0;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								#endif
							 |