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