xref: /openbsd-src/usr.sbin/installboot/util.c (revision 4a5d5189481afe844124661f09aeaa4d60871d36)
1*4a5d5189Svisa /*	$OpenBSD: util.c,v 1.16 2022/02/03 10:25:14 visa Exp $	*/
246339098Sjsing 
346339098Sjsing /*
446339098Sjsing  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
546339098Sjsing  *
646339098Sjsing  * Permission to use, copy, modify, and distribute this software for any
746339098Sjsing  * purpose with or without fee is hereby granted, provided that the above
846339098Sjsing  * copyright notice and this permission notice appear in all copies.
946339098Sjsing  *
1046339098Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1146339098Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1246339098Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1346339098Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1446339098Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1546339098Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1646339098Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1746339098Sjsing  */
1846339098Sjsing 
197762a34bSjsing #include <sys/stat.h>
2046339098Sjsing #include <err.h>
21f66515a4Skrw #include <errno.h>
227762a34bSjsing #include <fcntl.h>
23*4a5d5189Svisa #include <stdarg.h>
2446339098Sjsing #include <stdio.h>
2546339098Sjsing #include <stdlib.h>
2646339098Sjsing #include <string.h>
277762a34bSjsing #include <unistd.h>
289b2ea772Sderaadt #include <limits.h>
296520caa8Sjcs #include <libgen.h>
3046339098Sjsing 
3146339098Sjsing #include "installboot.h"
3246339098Sjsing 
339b2ea772Sderaadt #define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
349b2ea772Sderaadt 
3510588eb2Sjsing #define BUFSIZE 512
367762a34bSjsing 
37597864b7Skrw int
filecopy(const char * srcfile,const char * dstfile)387762a34bSjsing filecopy(const char *srcfile, const char *dstfile)
397762a34bSjsing {
407762a34bSjsing 	struct stat sb;
41e09cbf07Skrw 	ssize_t sz, n;
42e9230ec0Skrw 	int sfd, dfd;
436a1403f6Sjsing 	char *buf;
447762a34bSjsing 
457762a34bSjsing 	sfd = open(srcfile, O_RDONLY);
46597864b7Skrw 	if (sfd == -1) {
47597864b7Skrw 		warn("open %s", srcfile);
48597864b7Skrw 		return (-1);
49597864b7Skrw 	}
50597864b7Skrw 	if (fstat(sfd, &sb) == -1) {
51597864b7Skrw 		warn("fstat");
52597864b7Skrw 		return (-1);
53597864b7Skrw 	}
54e09cbf07Skrw 	sz = sb.st_size;
557762a34bSjsing 
56a80e7654Svisa 	dfd = open(dstfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
57597864b7Skrw 	if (dfd == -1) {
58597864b7Skrw 		warn("open %s", dstfile);
59597864b7Skrw 		return (-1);
60597864b7Skrw 	}
616a1403f6Sjsing 	if (fchown(dfd, 0, 0) == -1)
62597864b7Skrw 		if (errno != EINVAL) {
63597864b7Skrw 			warn("chown");
64597864b7Skrw 			return (-1);
65597864b7Skrw 		}
66597864b7Skrw 	if (fchmod(dfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
67597864b7Skrw 		warn("chmod");
68597864b7Skrw 		return (-1);
69597864b7Skrw 	}
707762a34bSjsing 
7143aa4f76Sjsg 	if ((buf = malloc(BUFSIZE)) == NULL) {
7243aa4f76Sjsg 		warn("malloc");
7343aa4f76Sjsg 		return (-1);
7443aa4f76Sjsg 	}
7543aa4f76Sjsg 
767762a34bSjsing 	while (sz > 0) {
779b2ea772Sderaadt 		n = MINIMUM(sz, BUFSIZE);
78597864b7Skrw 		if ((n = read(sfd, buf, n)) == -1) {
79597864b7Skrw 			warn("read");
8043aa4f76Sjsg 			free(buf);
81597864b7Skrw 			return (-1);
82597864b7Skrw 		}
837762a34bSjsing 		sz -= n;
84597864b7Skrw 		if (write(dfd, buf, n) != n) {
85597864b7Skrw 			warn("write");
8643aa4f76Sjsg 			free(buf);
87597864b7Skrw 			return (-1);
88597864b7Skrw 		}
897762a34bSjsing 	}
907762a34bSjsing 
91e09cbf07Skrw 	ftruncate(dfd, sb.st_size);
926a1403f6Sjsing 
937762a34bSjsing 	close(dfd);
947762a34bSjsing 	close(sfd);
957762a34bSjsing 	free(buf);
96597864b7Skrw 
97597864b7Skrw 	return (0);
987762a34bSjsing }
997762a34bSjsing 
10046339098Sjsing char *
fileprefix(const char * base,const char * path)10146339098Sjsing fileprefix(const char *base, const char *path)
10246339098Sjsing {
1036520caa8Sjcs 	char *r = NULL, *d, *b, *s;
10446339098Sjsing 	int n;
10546339098Sjsing 
106597864b7Skrw 	if ((s = malloc(PATH_MAX)) == NULL) {
107597864b7Skrw 		warn("malloc");
108597864b7Skrw 		return (NULL);
109597864b7Skrw 	}
11046339098Sjsing 	n = snprintf(s, PATH_MAX, "%s/%s", base, path);
111515e489cSderaadt 	if (n < 0 || n >= PATH_MAX) {
112597864b7Skrw 		warn("snprintf");
1136520caa8Sjcs 		goto err;
114597864b7Skrw 	}
1156520caa8Sjcs 	if ((d = dirname(s)) == NULL) {
1166520caa8Sjcs 		warn("dirname");
1176520caa8Sjcs 		goto err;
1186520caa8Sjcs 	}
1196520caa8Sjcs 	if ((r = realpath(d, NULL)) == NULL) {
120597864b7Skrw 		warn("realpath");
1216520caa8Sjcs 		goto err;
122597864b7Skrw 	}
1236520caa8Sjcs 	if ((b = basename(s)) == NULL) {
1246520caa8Sjcs 		warn("basename");
1256520caa8Sjcs 		goto err;
1266520caa8Sjcs 	}
1276520caa8Sjcs 	n = snprintf(s, PATH_MAX, "%s/%s", r, b);
128515e489cSderaadt 	if (n < 0 || n >= PATH_MAX) {
1296520caa8Sjcs 		warn("snprintf");
1306520caa8Sjcs 		goto err;
1316520caa8Sjcs 	}
132b3c2788bSmiko 	free(r);
1336520caa8Sjcs 	return (s);
13446339098Sjsing 
1356520caa8Sjcs err:
1366520caa8Sjcs 	free(s);
1376520caa8Sjcs 	free(r);
1386520caa8Sjcs 	return (NULL);
13946339098Sjsing }
140f66515a4Skrw 
141*4a5d5189Svisa int
fileprintf(const char * filename,const char * fmt,...)142*4a5d5189Svisa fileprintf(const char *filename, const char *fmt, ...)
143*4a5d5189Svisa {
144*4a5d5189Svisa 	va_list ap;
145*4a5d5189Svisa 	int fd, ret;
146*4a5d5189Svisa 	int rslt = -1;
147*4a5d5189Svisa 
148*4a5d5189Svisa 	fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC,
149*4a5d5189Svisa 	    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
150*4a5d5189Svisa 	if (fd == -1) {
151*4a5d5189Svisa 		warn("open %s", filename);
152*4a5d5189Svisa 		return (-1);
153*4a5d5189Svisa 	}
154*4a5d5189Svisa 	if (fchown(fd, 0, 0) == -1) {
155*4a5d5189Svisa 		if (errno != EINVAL) {
156*4a5d5189Svisa 			warn("chown");
157*4a5d5189Svisa 			goto err;
158*4a5d5189Svisa 		}
159*4a5d5189Svisa 	}
160*4a5d5189Svisa 	if (fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
161*4a5d5189Svisa 		warn("chmod");
162*4a5d5189Svisa 		goto err;
163*4a5d5189Svisa 	}
164*4a5d5189Svisa 
165*4a5d5189Svisa 	va_start(ap, fmt);
166*4a5d5189Svisa 	ret = vdprintf(fd, fmt, ap);
167*4a5d5189Svisa 	va_end(ap);
168*4a5d5189Svisa 
169*4a5d5189Svisa 	if (ret < 0) {
170*4a5d5189Svisa 		warn("vdprintf");
171*4a5d5189Svisa 		goto err;
172*4a5d5189Svisa 	}
173*4a5d5189Svisa 
174*4a5d5189Svisa 	rslt = 0;
175*4a5d5189Svisa 
176*4a5d5189Svisa err:
177*4a5d5189Svisa 	close(fd);
178*4a5d5189Svisa 	return (rslt);
179*4a5d5189Svisa }
180*4a5d5189Svisa 
181f66515a4Skrw /*
182f66515a4Skrw  * Adapted from Hacker's Delight crc32b().
183f66515a4Skrw  *
184f66515a4Skrw  * To quote http://www.hackersdelight.org/permissions.htm :
185f66515a4Skrw  *
186f66515a4Skrw  * "You are free to use, copy, and distribute any of the code on
187f66515a4Skrw  *  this web site, whether modified by you or not. You need not give
188f66515a4Skrw  *  attribution. This includes the algorithms (some of which appear
189f66515a4Skrw  *  in Hacker's Delight), the Hacker's Assistant, and any code submitted
190f66515a4Skrw  *  by readers. Submitters implicitly agree to this."
191f66515a4Skrw  */
192f66515a4Skrw u_int32_t
crc32(const u_char * buf,const u_int32_t size)193f66515a4Skrw crc32(const u_char *buf, const u_int32_t size)
194f66515a4Skrw {
195f66515a4Skrw 	int j;
196f66515a4Skrw 	u_int32_t i, byte, crc, mask;
197f66515a4Skrw 
198f66515a4Skrw 	crc = 0xFFFFFFFF;
199f66515a4Skrw 
200f66515a4Skrw 	for (i = 0; i < size; i++) {
201f66515a4Skrw 		byte = buf[i];			/* Get next byte. */
202f66515a4Skrw 		crc = crc ^ byte;
203f66515a4Skrw 		for (j = 7; j >= 0; j--) {	/* Do eight times. */
204f66515a4Skrw 			mask = -(crc & 1);
205f66515a4Skrw 			crc = (crc >> 1) ^ (0xEDB88320 & mask);
206f66515a4Skrw 		}
207f66515a4Skrw 	}
208f66515a4Skrw 
209f66515a4Skrw 	return ~crc;
210f66515a4Skrw }
211