xref: /openbsd/usr.sbin/installboot/util.c (revision 4a5d5189)
1 /*	$OpenBSD: util.c,v 1.16 2022/02/03 10:25:14 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/stat.h>
20 #include <err.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <limits.h>
29 #include <libgen.h>
30 
31 #include "installboot.h"
32 
33 #define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
34 
35 #define BUFSIZE 512
36 
37 int
filecopy(const char * srcfile,const char * dstfile)38 filecopy(const char *srcfile, const char *dstfile)
39 {
40 	struct stat sb;
41 	ssize_t sz, n;
42 	int sfd, dfd;
43 	char *buf;
44 
45 	sfd = open(srcfile, O_RDONLY);
46 	if (sfd == -1) {
47 		warn("open %s", srcfile);
48 		return (-1);
49 	}
50 	if (fstat(sfd, &sb) == -1) {
51 		warn("fstat");
52 		return (-1);
53 	}
54 	sz = sb.st_size;
55 
56 	dfd = open(dstfile, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
57 	if (dfd == -1) {
58 		warn("open %s", dstfile);
59 		return (-1);
60 	}
61 	if (fchown(dfd, 0, 0) == -1)
62 		if (errno != EINVAL) {
63 			warn("chown");
64 			return (-1);
65 		}
66 	if (fchmod(dfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
67 		warn("chmod");
68 		return (-1);
69 	}
70 
71 	if ((buf = malloc(BUFSIZE)) == NULL) {
72 		warn("malloc");
73 		return (-1);
74 	}
75 
76 	while (sz > 0) {
77 		n = MINIMUM(sz, BUFSIZE);
78 		if ((n = read(sfd, buf, n)) == -1) {
79 			warn("read");
80 			free(buf);
81 			return (-1);
82 		}
83 		sz -= n;
84 		if (write(dfd, buf, n) != n) {
85 			warn("write");
86 			free(buf);
87 			return (-1);
88 		}
89 	}
90 
91 	ftruncate(dfd, sb.st_size);
92 
93 	close(dfd);
94 	close(sfd);
95 	free(buf);
96 
97 	return (0);
98 }
99 
100 char *
fileprefix(const char * base,const char * path)101 fileprefix(const char *base, const char *path)
102 {
103 	char *r = NULL, *d, *b, *s;
104 	int n;
105 
106 	if ((s = malloc(PATH_MAX)) == NULL) {
107 		warn("malloc");
108 		return (NULL);
109 	}
110 	n = snprintf(s, PATH_MAX, "%s/%s", base, path);
111 	if (n < 0 || n >= PATH_MAX) {
112 		warn("snprintf");
113 		goto err;
114 	}
115 	if ((d = dirname(s)) == NULL) {
116 		warn("dirname");
117 		goto err;
118 	}
119 	if ((r = realpath(d, NULL)) == NULL) {
120 		warn("realpath");
121 		goto err;
122 	}
123 	if ((b = basename(s)) == NULL) {
124 		warn("basename");
125 		goto err;
126 	}
127 	n = snprintf(s, PATH_MAX, "%s/%s", r, b);
128 	if (n < 0 || n >= PATH_MAX) {
129 		warn("snprintf");
130 		goto err;
131 	}
132 	free(r);
133 	return (s);
134 
135 err:
136 	free(s);
137 	free(r);
138 	return (NULL);
139 }
140 
141 int
fileprintf(const char * filename,const char * fmt,...)142 fileprintf(const char *filename, const char *fmt, ...)
143 {
144 	va_list ap;
145 	int fd, ret;
146 	int rslt = -1;
147 
148 	fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC,
149 	    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
150 	if (fd == -1) {
151 		warn("open %s", filename);
152 		return (-1);
153 	}
154 	if (fchown(fd, 0, 0) == -1) {
155 		if (errno != EINVAL) {
156 			warn("chown");
157 			goto err;
158 		}
159 	}
160 	if (fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
161 		warn("chmod");
162 		goto err;
163 	}
164 
165 	va_start(ap, fmt);
166 	ret = vdprintf(fd, fmt, ap);
167 	va_end(ap);
168 
169 	if (ret < 0) {
170 		warn("vdprintf");
171 		goto err;
172 	}
173 
174 	rslt = 0;
175 
176 err:
177 	close(fd);
178 	return (rslt);
179 }
180 
181 /*
182  * Adapted from Hacker's Delight crc32b().
183  *
184  * To quote http://www.hackersdelight.org/permissions.htm :
185  *
186  * "You are free to use, copy, and distribute any of the code on
187  *  this web site, whether modified by you or not. You need not give
188  *  attribution. This includes the algorithms (some of which appear
189  *  in Hacker's Delight), the Hacker's Assistant, and any code submitted
190  *  by readers. Submitters implicitly agree to this."
191  */
192 u_int32_t
crc32(const u_char * buf,const u_int32_t size)193 crc32(const u_char *buf, const u_int32_t size)
194 {
195 	int j;
196 	u_int32_t i, byte, crc, mask;
197 
198 	crc = 0xFFFFFFFF;
199 
200 	for (i = 0; i < size; i++) {
201 		byte = buf[i];			/* Get next byte. */
202 		crc = crc ^ byte;
203 		for (j = 7; j >= 0; j--) {	/* Do eight times. */
204 			mask = -(crc & 1);
205 			crc = (crc >> 1) ^ (0xEDB88320 & mask);
206 		}
207 	}
208 
209 	return ~crc;
210 }
211