emergency commit
[cl-cudd.git] / distr / util / saveimage.c
blob32332ef40684446acce3a23c7e8facf0f46a7109
1 /* LINTLIBRARY */
4 /*
5 * saveimage.c --
7 * Function to save an executable copy of the current process's
8 * image in a file.
12 #include <stdio.h>
13 #include "util.h"
15 #ifdef BSD
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <a.out.h>
19 #include <errno.h>
21 extern int errno;
23 #define BUFSIZE 8192
25 extern long lseek(); /* For lint */
26 extern int getpagesize();
27 extern char *sbrk();
29 static int copy_file();
30 static int pad_file();
33 int
34 util_save_image(char const *orig_file_name, char const *save_file_name)
36 int origFd = -1, saveFd = -1;
37 char *start_data, *end_data, *start_text, *end_round;
38 struct exec old_hdr, new_hdr;
39 struct stat old_stat;
40 int n, page_size, length_text, length_data;
42 if ((origFd = open(orig_file_name, 0)) < 0) {
43 perror(orig_file_name);
44 (void) fprintf(stderr, "Cannot open original a.out file\n");
45 goto bad;
48 if (fstat(origFd, &old_stat) < 0) {
49 perror(orig_file_name);
50 (void) fprintf(stderr, "Cannot stat original a.out file\n");
51 goto bad;
55 * Read the a.out header from the original file.
57 if (read(origFd, (char *) &old_hdr, sizeof(old_hdr)) != sizeof(old_hdr)) {
58 perror(orig_file_name);
59 (void) fprintf(stderr, "Cannot read original a.out header\n");
60 goto bad;
62 if (N_BADMAG(old_hdr)) {
63 (void) fprintf(stderr, "File %s has a bad magic number (%o)\n",
64 orig_file_name, old_hdr.a_magic);
65 goto bad;
67 if (old_hdr.a_magic != ZMAGIC) {
68 (void) fprintf(stderr, "File %s is not demand-paged\n", orig_file_name);
69 goto bad;
73 * Open the output file.
75 if (access(save_file_name, /* F_OK */ 0) == 0) {
76 (void) unlink(save_file_name);
78 if ((saveFd = creat(save_file_name, 0777)) < 0) {
79 if (errno == ETXTBSY) {
80 (void) unlink(save_file_name);
81 saveFd = creat(save_file_name, 0777);
83 if (saveFd < 0) {
84 perror(save_file_name);
85 (void) fprintf(stderr, "Cannot create save file.\n");
86 goto bad;
91 * Find out how far the data segment extends.
93 new_hdr = old_hdr;
94 end_data = sbrk(0);
95 page_size = getpagesize();
96 n = ((((int) end_data) + page_size - 1) / page_size) * page_size;
97 end_round = (char *) n;
98 if (end_round > end_data) {
99 end_data = sbrk(end_round - end_data);
102 #ifdef vax
103 start_text = 0;
104 length_text = new_hdr.a_text;
105 start_data = (char *) old_hdr.a_text;
106 length_data = end_data - start_data;
107 #endif vax
108 #ifdef sun
109 start_text = (char *) N_TXTADDR(old_hdr) + sizeof(old_hdr);
110 length_text = old_hdr.a_text - sizeof(old_hdr);
111 start_data = (char *) N_DATADDR(old_hdr);
112 length_data = end_data - start_data;
113 #endif sun
114 new_hdr.a_data = end_data - start_data;
115 new_hdr.a_bss = 0;
118 * First, the header plus enough pad to extend up to N_TXTOFF.
120 if (write(saveFd, (char *) &new_hdr, (int) sizeof(new_hdr)) !=
121 sizeof(new_hdr)) {
122 perror("write");
123 (void) fprintf(stderr, "Error while copying header.\n");
124 goto bad;
126 if (! pad_file(saveFd, N_TXTOFF(old_hdr) - sizeof(new_hdr))) {
127 (void) fprintf(stderr, "Error while padding.\n");
128 goto bad;
133 * Copy our text segment
135 if (write(saveFd, start_text, length_text) != length_text) {
136 perror("write");
137 (void) fprintf(stderr, "Error while copying text segment.\n");
138 goto bad;
143 * Copy our data segment
145 if (write(saveFd, start_data, length_data) != length_data) {
146 perror("write");
147 (void) fprintf(stderr, "Error while copying data segment.\n");
148 goto bad;
152 * Copy the symbol table and everything else.
153 * This takes us to the end of the original file.
155 (void) lseek(origFd, (long) N_SYMOFF(old_hdr), 0);
156 if (! copy_file(origFd, saveFd, old_stat.st_size - N_SYMOFF(old_hdr))) {
157 (void) fprintf(stderr, "Error while copying symbol table.\n");
158 goto bad;
160 (void) close(origFd);
161 (void) close(saveFd);
162 return 1;
164 bad:
165 if (origFd >= 0) (void) close(origFd);
166 if (saveFd >= 0) (void) close(saveFd);
167 return 0;
171 static int
172 copy_file(inFd, outFd, nbytes)
173 int inFd, outFd;
174 unsigned long nbytes;
176 char buf[BUFSIZE];
177 int nread, ntoread;
179 while (nbytes > 0) {
180 ntoread = nbytes;
181 if (ntoread > sizeof buf) ntoread = sizeof buf;
182 if ((nread = read(inFd, buf, ntoread)) != ntoread) {
183 perror("read");
184 return (0);
186 if (write(outFd, buf, nread) != nread) {
187 perror("write");
188 return (0);
190 nbytes -= nread;
193 return (1);
197 static int
198 pad_file(outFd, nbytes)
199 int outFd;
200 int nbytes;
202 char buf[BUFSIZE];
203 int nzero;
205 nzero = (nbytes > sizeof(buf)) ? sizeof(buf) : nbytes;
206 bzero(buf, nzero);
207 while (nbytes > 0) {
208 nzero = (nbytes > sizeof(buf)) ? sizeof(buf) : nbytes;
209 if (write(outFd, buf, nzero) != nzero) {
210 perror("write");
211 return (0);
213 nbytes -= nzero;
216 return (1);
218 #else
220 /* ARGSUSED */
222 util_save_image(char const *orig_file_name, char const *save_file_name)
224 (void) fprintf(stderr,
225 "util_save_image: not implemented on your operating system\n");
226 return 0;
229 #endif