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

/* 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