xref: /plan9/sys/src/cmd/strip.c (revision 4d44ba9b9ee4246ddbd96c7fcaf0918ab92ab35a)
1 #include <u.h>
2 #include <libc.h>
3 #include <a.out.h>
4 
5 int	strip(char*);
6 int	stripfilt(int, int);
7 void
8 main(int argc, char *argv[])
9 {
10 	int i;
11 	int rv;
12 
13 	rv = 0;
14 
15 	if(argc == 1) {
16 		if(stripfilt(0, 1))
17 			exits("error");
18 		exits(0);
19 	}
20 
21 	for(i = 1; i < argc; i++)
22 		rv |= strip(argv[i]);
23 	if(rv)
24 		exits("error");
25 	exits(0);
26 }
27 
28 long
29 ben(long xen)
30 {
31 	union
32 	{
33 		long	xen;
34 		uchar	uch[sizeof(long)];
35 	} u;
36 
37 	u.xen = xen;
38 	return (u.uch[0] << 24) | (u.uch[1] << 16) | (u.uch[2] << 8) | (u.uch[3] << 0);
39 }
40 
41 int
42 stripfilt(int in, int out)
43 {
44 	Exec exec;
45 	int i, j, n, m, len;
46 	char buf[8192];
47 
48 	/*
49 	 * read header
50 	 */
51 
52 	if(readn(in, &exec, sizeof(Exec)) != sizeof(Exec)) {
53 		fprint(2, "strip: short read\n");
54 		return 1;
55 	}
56 	i = ben(exec.magic);
57 	for (j = MIN_MAGIC; j <= MAX_MAGIC; j++)
58 		if (i == _MAGIC(j))
59 			break;
60 	if (j > MAX_MAGIC) {
61 		fprint(2, "strip: not a recognizable binary\n");
62 		return 1;
63 	}
64 
65 	len = ben(exec.data) + ben(exec.text);
66 
67 	/*
68 	 *  copy exec, text and data
69 	 */
70 	exec.syms = 0;
71 	exec.spsz = 0;
72 	exec.pcsz = 0;
73 	write(out, &exec, sizeof(exec));
74 
75 	for(n=0; n<len; n+=m) {
76 		m = len - n;
77 		if(m > sizeof(buf))
78 			m = sizeof(buf);
79 		if((m = read(in, buf, m)) < 0) {
80 			fprint(2, "strip: premature eof: %r\n");
81 			return 1;
82 		}
83 		if(write(out, buf, m) != m) {
84 			fprint(2, "strip: write error; %r\n");
85 			return 1;
86 		}
87 	}
88 
89 	return 0;
90 }
91 
92 
93 int
94 strip(char *file)
95 {
96 	int fd;
97 	Exec exec;
98 	char *data;
99 	Dir *d;
100 	long n, len;
101 	int i, j;
102 
103 	/*
104 	 *  make sure file is executable
105 	 */
106 	d = dirstat(file);
107 	if(d == nil){
108 		perror(file);
109 		return 1;
110 	}
111 	if((d->qid.path & (DMDIR|DMAPPEND|DMEXCL))){
112 		fprint(2, "strip: %s must be executable\n", file);
113 		return 1;
114 	}
115 	/*
116 	 *  read its header and see if that makes sense
117 	 */
118 	fd = open(file, OREAD);
119 	if(fd < 0){
120 		perror(file);
121 		free(d);
122 		return 1;
123 	}
124 	n = read(fd, &exec, sizeof exec);
125 	if (n != sizeof(exec)) {
126 		fprint(2, "strip: Unable to read header of %s\n", file);
127 		close(fd);
128 		free(d);
129 		return 1;
130 	}
131 	i = ben(exec.magic);
132 	for (j = MIN_MAGIC; j <= MAX_MAGIC; j++)
133 		if (i == _MAGIC(j))
134 			break;
135 	if (j > MAX_MAGIC) {
136 		fprint(2, "strip: %s is not a recognizable binary\n", file);
137 		close(fd);
138 		free(d);
139 		return 1;
140 	}
141 
142 	len = ben(exec.data) + ben(exec.text);
143 	if(len+sizeof(exec) == d->length) {
144 		fprint(2, "strip: %s is already stripped\n", file);
145 		close(fd);
146 		free(d);
147 		return 0;
148 	}
149 	if(len+sizeof(exec) > d->length) {
150 		fprint(2, "strip: %s has strange length\n", file);
151 		close(fd);
152 		free(d);
153 		return 1;
154 	}
155 	/*
156 	 *  allocate a huge buffer, copy the header into it, then
157 	 *  read the file.
158 	 */
159 	data = malloc(len+sizeof(exec));
160 	if (!data) {
161 		fprint(2, "strip: Malloc failure. %s too big to strip.\n", file);
162 		close(fd);
163 		free(d);
164 		return 1;
165 	}
166 	/*
167 	 *  copy exec, text and data
168 	 */
169 	exec.syms = 0;
170 	exec.spsz = 0;
171 	exec.pcsz = 0;
172 	memcpy(data, &exec, sizeof(exec));
173 	n = read(fd, data+sizeof(exec), len);
174 	if (n != len) {
175 		perror(file);
176 		close(fd);
177 		free(d);
178 		return 1;
179 	}
180 	close(fd);
181 	if(remove(file) < 0) {
182 		perror(file);
183 		free(data);
184 		free(d);
185 		return 1;
186 	}
187 	fd = create(file, OWRITE, d->mode);
188 	if (fd < 0) {
189 		perror(file);
190 		free(data);
191 		free(d);
192 		return 1;
193 	}
194 	n = write(fd, data, len+sizeof(exec));
195 	if (n != len+sizeof(exec)) {
196 		perror(file);
197 		close(fd);
198 		free(data);
199 		free(d);
200 		return 1;
201 	}
202 	close(fd);
203 	free(data);
204 	free(d);
205 	return 0;
206 }
207