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
37int
38filecopy(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
100char *
101fileprefix(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
135err:
136	free(s);
137	free(r);
138	return (NULL);
139}
140
141int
142fileprintf(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
176err:
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 */
192u_int32_t
193crc32(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